summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cpu.sym1
-rw-r--r--global.c4
-rw-r--r--parser.y4
-rw-r--r--routine.c6
-rw-r--r--server.c167
-rw-r--r--type.c36
-rw-r--r--type.h5
-rw-r--r--user.c123
-rw-r--r--utils.c28
9 files changed, 279 insertions, 95 deletions
diff --git a/cpu.sym b/cpu.sym
index bee12f0..1ac2fae 100644
--- a/cpu.sym
+++ b/cpu.sym
@@ -105,6 +105,7 @@ expr sizeof(float) sizeof_float
expr sizeof(double) sizeof_double
expr sizeof(uintptr_t) sizeof_uintptr_t
expr sizeof(intptr_t) sizeof_intptr_t
+expr (sizeof(uintptr_t)*8) sizeof_uintptr_t_in_bits
expr sizeof(mach_msg_header_t) sizeof_mach_msg_header_t
expr sizeof(mach_msg_type_long_t) sizeof_mach_msg_type_long_t
expr sizeof(mach_msg_type_t) sizeof_mach_msg_type_t
diff --git a/global.c b/global.c
index 0ef1dca..bac667c 100644
--- a/global.c
+++ b/global.c
@@ -65,8 +65,8 @@ string_t InternalHeaderFileName = strNULL;
string_t UserFileName = strNULL;
string_t ServerFileName = strNULL;
-size_t port_size = port_name_size;
-size_t port_size_in_bits = port_name_size_in_bits;
+size_t port_size = sizeof_uintptr_t;
+size_t port_size_in_bits = sizeof_uintptr_t_in_bits;
size_t complex_alignof = desired_complex_alignof;
void
diff --git a/parser.y b/parser.y
index cac3379..5a73af8 100644
--- a/parser.y
+++ b/parser.y
@@ -210,10 +210,6 @@ Subsystem : SubsystemStart SubsystemMods
IsKernelUser ? ", KernelUser" : "",
IsKernelServer ? ", KernelServer" : "");
}
- if (IsKernelUser || IsKernelServer) {
- port_size = vm_offset_size;
- port_size_in_bits = vm_offset_size_in_bits;
- }
init_type();
}
;
diff --git a/routine.c b/routine.c
index 3ae9298..8909f4d 100644
--- a/routine.c
+++ b/routine.c
@@ -517,6 +517,12 @@ rtAugmentArgKind(argument_t *arg)
{
arg->argKind = akAddFeature(arg->argKind, akbPointer);
}
+ if (akCheck(arg->argKind, akbSendRcv) &&
+ IS_64BIT_ABI &&
+ it->itUserlandPort &&
+ akCheck(arg->argKind, akbIndefinite)) {
+ arg->argKind = akAddFeature(arg->argKind, akbPointer);
+ }
}
/* arg->argType may be NULL in this function */
diff --git a/server.c b/server.c
index 00ca3f2..973e1f7 100644
--- a/server.c
+++ b/server.c
@@ -455,10 +455,27 @@ WriteTypeCheck(FILE *file, const argument_t *arg)
arg->argRequestPos, arg->argTTName,
arg->argLongForm ? "l" : "",
it->itNumber);
- fprintf(file, "\t (In%dP->%s.msgt%s_size != %d)))\n",
- arg->argRequestPos, arg->argTTName,
- arg->argLongForm ? "l" : "",
- it->itSize);
+ if (IS_64BIT_ABI && it->itUserlandPort && arg->argLongForm) {
+ /* 64 bit inlined ports are 8 bytes long but we use mach_port_name_t when passing them out of line. */
+ fprintf(file, "\t (In%dP->%s.msgtl_size != %d && In%dP->%s.msgtl_header.msgt_inline == TRUE) || \n",
+ arg->argRequestPos,
+ arg->argTTName,
+ it->itSize,
+ arg->argRequestPos,
+ arg->argTTName);
+ fprintf(file, "\t (In%dP->%s.msgtl_size != %d && In%dP->%s.msgtl_header.msgt_inline == FALSE)",
+ arg->argRequestPos,
+ arg->argTTName,
+ port_name_size_in_bits,
+ arg->argRequestPos,
+ arg->argTTName);
+ } else {
+ fprintf(file, "\t (In%dP->%s.msgt%s_size != %d)",
+ arg->argRequestPos, arg->argTTName,
+ arg->argLongForm ? "l" : "",
+ it->itSize);
+ }
+ fprintf(file, "))\n");
}
WriteMsgError(file, "MIG_BAD_ARGUMENTS");
fprintf(file, "#endif\t/* TypeCheck */\n");
@@ -565,6 +582,7 @@ static const char *
InArgMsgField(const argument_t *arg)
{
static char buffer[100];
+ const ipc_type_t *it = arg->argType;
/*
* Inside the kernel, the request and reply port fields
@@ -588,6 +606,9 @@ static void
WriteExtractArgValue(FILE *file, const argument_t *arg)
{
const ipc_type_t *it = arg->argType;
+ const bool is_inlined_port = it->itUserlandPort && it->itInLine &&
+ akIdent(arg->argKind) != akeRequestPort && akIdent(arg->argKind) != akeReplyPort;
+ const char* arg_suffix = is_inlined_port ? ".name" : "";
bool have_payload;
if (arg->argMultiplier > 1)
@@ -618,17 +639,18 @@ WriteExtractArgValue(FILE *file, const argument_t *arg)
fprintf(file, "\t%s = %s;",
arg->argVarName, InArgMsgField(arg));
else
- WriteCopyType(file, it, "%s", "/* %s */ %s(%s)",
+ WriteCopyType(file, it, "%s", "/* %s */ %s(%s%s)",
arg->argVarName, it->itInTrans,
- InArgMsgField(arg));
+ InArgMsgField(arg), arg_suffix);
} else {
- WriteCopyType(file, it, "%s", "/* %s */ %s(%s)",
+ WriteCopyType(file, it, "%s", "/* %s */ %s(%s%s)",
arg->argVarName, it->itInTrans,
- InArgMsgField(arg));
+ InArgMsgField(arg), arg_suffix);
}
- } else
- WriteCopyType(file, it, "%s", "/* %s */ %s",
- arg->argVarName, InArgMsgField(arg));
+ } else {
+ WriteCopyType(file, it, "%s", "/* %s */ %s%s",
+ arg->argVarName, InArgMsgField(arg), arg_suffix);
+ }
fprintf(file, "\n");
}
@@ -669,8 +691,10 @@ WriteInitializePtr(FILE *file, const argument_t *arg)
fprintf(file, "\t%sP = %s;\n",
arg->argVarName, arg->argVarName);
else
- fprintf(file, "\t%sP = OutP->%s;\n",
- arg->argVarName, arg->argMsgField);
+ fprintf(file, "\t%sP = %sOutP->%s;\n",
+ arg->argVarName,
+ arg->argType->itUserlandPort ? "(mach_port_t *)" : "",
+ arg->argMsgField);
}
static void
@@ -745,12 +769,34 @@ WriteExtractArg(FILE *file, const argument_t *arg)
if (akCheckAll(arg->argKind, akbReturnSnd|akbPointer))
WriteInitializePtr(file, arg);
+ if (akCheckAll(arg->argKind, akbSendRcv|akbPointer)) {
+ if (akCheck(arg->argKind, akbIndefinite)) {
+ fprintf(file, "\tif (In%dP->%s%s.msgt_inline) {\n",
+ arg->argRequestPos, arg->argTTName, arg->argLongForm ? ".msgtl_header" : "");
+ fprintf(file, "\t\t%sP = (mach_port_t *)%s;\n", arg->argVarName, InArgMsgField(arg));
+ fprintf(file, "\t\tmach_msg_type_number_t i;\n");
+ fprintf(file, "\t\t/* Resizes the mach_port_name_inlined_t input array as an array of mach_port_name_t. */\n");
+ fprintf(file, "\t\tfor (i = 1; i < In%dP->%s.msgt%s_number; i++) {\n",
+ arg->argRequestPos, arg->argTTName, arg->argLongForm ? "l" : "");
+ fprintf(file, "\t\t\t%sP[i] = %s[i].name;\n", arg->argVarName, InArgMsgField(arg));
+ fprintf(file, "\t\t}\n");
+ fprintf(file, "\t} else {\n");
+ fprintf(file, "\t\t%sP = %s%s;\n", arg->argVarName, InArgMsgField(arg), OOLPostfix);
+ fprintf(file, "\t}\n");
+ }
+ else
+ assert(false);
+ }
}
static void
WriteServerCallArg(FILE *file, const argument_t *arg)
{
const ipc_type_t *it = arg->argType;
+ const bool is_inlined_port = it->itUserlandPort &&
+ akIdent(arg->argKind) != akeRequestPort && akIdent(arg->argKind) != akeReplyPort && it->itInLine;
+ const char* arg_suffix = is_inlined_port ? ".name" : "";
+
bool NeedClose = false;
if (IsKernelServer) {
@@ -786,16 +832,17 @@ WriteServerCallArg(FILE *file, const argument_t *arg)
arg->argRequestPos,
arg->argTTName,
arg->argLongForm ? ".msgtl_header" : "");
- fprintf(file, "? %s ", InArgMsgField(arg));
+ fprintf(file, "? %s%s ", it->itUserlandPort ? "(mach_port_t *)" : "",
+ InArgMsgField(arg));
fprintf(file, ": %s%s",
InArgMsgField(arg),
OOLPostfix);
}
else
- fprintf(file, "%s", InArgMsgField(arg));
+ fprintf(file, "%s%s", InArgMsgField(arg), arg_suffix);
}
else
- fprintf(file, "OutP->%s", arg->argMsgField);
+ fprintf(file, "OutP->%s%s", arg->argMsgField, arg_suffix);
if (NeedClose)
fprintf(file, ")");
@@ -818,7 +865,7 @@ WriteDestroyArg(FILE *file, const argument_t *arg)
*/
argument_t *count = arg->argCount;
ipc_type_t *btype = it->itElement;
- int multiplier = btype->itTypeSize / btype->itNumber;
+ int multiplier = it->itUserlandPort ? port_name_size : btype->itTypeSize / btype->itNumber;
fprintf(file, "\tif (OutP->%s == KERN_SUCCESS)\n",
arg->argRoutine->rtRetCode->argMsgField);
@@ -938,6 +985,8 @@ static void
WritePackArgValue(FILE *file, const argument_t *arg)
{
const ipc_type_t *it = arg->argType;
+ const bool is_inlined_port = it->itUserlandPort && it->itInLine;
+ const char* arg_suffix = is_inlined_port ? ".name" : "";
fprintf(file, "\n");
@@ -965,6 +1014,7 @@ WritePackArgValue(FILE *file, const argument_t *arg)
else {
argument_t *count = arg->argCount;
ipc_type_t *btype = it->itElement;
+ const bool is_64bit_port = IS_64BIT_ABI && btype->itUserlandPort;
/* Note btype->itNumber == count->argMultiplier */
@@ -988,26 +1038,41 @@ WritePackArgValue(FILE *file, const argument_t *arg)
arg->argTTName,
arg->argLongForm ? ".msgtl_header" : "",
arg->argDealloc->argVarName);
+ if (is_64bit_port) {
+ /* We are passing the ports out of line, so they will always have the same size as a port name. */
+ fprintf(file, "\t\tOutP->%s%s.msgt_size = %d;\n",
+ arg->argTTName,
+ arg->argLongForm ? ".msgtl_header" : "",
+ port_name_size_in_bits);
+ }
fprintf(file, "\t\tOutP->%s%s = %sP;\n",
- arg->argMsgField,
- OOLPostfix,
- arg->argVarName);
+ arg->argMsgField,
+ OOLPostfix,
+ arg->argVarName);
if (!arg->argRoutine->rtSimpleFixedReply)
fprintf(file, "\t\tmsgh_simple = FALSE;\n");
- fprintf(file, "\t}\n\telse {\n\t");
+ fprintf(file, "\t}\n\telse {\n");
}
- fprintf(file, "\tif (%s)\n", count->argVarName);
- if (it->itIndefinite)
- fprintf(file, "\t");
- fprintf(file, "\t\tmemcpy(OutP->%s, %s, ",
- arg->argMsgField, arg->argVarName);
- if (btype->itTypeSize > 1)
- fprintf(file, "%d * ",
- btype->itTypeSize);
- fprintf(file, "%s);\n",
- count->argVarName);
- if (it->itIndefinite)
- fprintf(file, "\t}\n");
+ fprintf(file, "\t\tif (%s) {\n", count->argVarName);
+ if (it->itIndefinite) {
+ if (is_64bit_port) {
+ fprintf(file, "\t\t\t/* Copy array of mach_port_name_t into mach_port_name_inlined_t. */\n");
+ fprintf(file, "\t\t\tmach_msg_type_number_t i;\n");
+ fprintf(file, "\t\t\tfor(i = 0; i < %s; i++) {\n", count->argVarName);
+ fprintf(file, "\t\t\t\t/* Clear the whole message with zeros. */\n");
+ fprintf(file, "\t\t\t\tOutP->%s[i].kernel_port_do_not_use = 0;\n", arg->argMsgField);
+ fprintf(file, "\t\t\t\tOutP->%s[i].name = %s[i];\n", arg->argMsgField, arg->argVarName);
+ fprintf(file, "\t\t\t}\n");
+ } else {
+ fprintf(file, "\t\t\tmemcpy(OutP->%s, %s, ",
+ arg->argMsgField, arg->argVarName);
+ if (btype->itTypeSize > 1)
+ fprintf(file, "%d * ", btype->itTypeSize);
+ fprintf(file, "%s);\n", count->argVarName);
+ }
+ }
+ fprintf(file, "\t\t}\n");
+ fprintf(file, "\t}\n");
}
}
else if (arg->argMultiplier > 1)
@@ -1015,12 +1080,12 @@ WritePackArgValue(FILE *file, const argument_t *arg)
arg->argMsgField,
arg->argMultiplier,
arg->argVarName);
- else if (it->itOutTrans != strNULL)
- WriteCopyType(file, it, "OutP->%s", "/* %s */ %s(%s)",
- arg->argMsgField, it->itOutTrans, arg->argVarName);
- else
- WriteCopyType(file, it, "OutP->%s", "/* %s */ %s",
- arg->argMsgField, arg->argVarName);
+ else if (it->itOutTrans != strNULL) {
+ WriteCopyType(file, it, "OutP->%s%s", "/* %s%s */ %s(%s)",
+ arg->argMsgField, arg_suffix, it->itOutTrans, arg->argVarName);
+ } else
+ WriteCopyType(file, it, "OutP->%s%s", "/* %s%s */ %s",
+ arg->argMsgField, arg_suffix, arg->argVarName);
}
static void
@@ -1198,11 +1263,14 @@ WritePackArg(FILE *file, const argument_t *arg)
fprintf(file, "\tOutP->%s = strlen(OutP->%s) + 1;\n",
arg->argCount->argMsgField, arg->argMsgField);
} else if (it->itIndefinite) {
+ const bool is_64bit_port = IS_64BIT_ABI && it->itUserlandPort;
+
/*
* We know that array is in reply message.
*/
- fprintf(file, "\tif (%sP != OutP->%s) {\n",
+ fprintf(file, "\tif (%sP != %sOutP->%s) {\n",
arg->argVarName,
+ it->itUserlandPort ? "(mach_port_t *)" : "",
arg->argMsgField);
fprintf(file, "\t\tOutP->%s%s.msgt_inline = FALSE;\n",
arg->argTTName,
@@ -1216,12 +1284,31 @@ WritePackArg(FILE *file, const argument_t *arg)
arg->argTTName,
arg->argLongForm ? ".msgtl_header" : "",
arg->argDealloc->argVarName);
+ if (is_64bit_port) {
+ /* We are passing the ports out of line, so they will always have the same size as a port name. */
+ fprintf(file, "\t\tOutP->%s%s.msgt_size = %d;\n",
+ arg->argTTName,
+ arg->argLongForm ? ".msgtl_header" : "",
+ port_name_size_in_bits);
+ }
fprintf(file, "\t\tOutP->%s%s = %sP;\n",
arg->argMsgField,
OOLPostfix,
arg->argVarName);
if (!arg->argRoutine->rtSimpleFixedReply)
fprintf(file, "\t\tmsgh_simple = FALSE;\n");
+ if (is_64bit_port) {
+ fprintf(file, "\t} else {\n");
+ fprintf(file, "\t\t/* Resize mach_port_name_t array into mach_port_name_inlined_t. */\n");
+ fprintf(file, "\t\t/* Work in reverse order to avoid overriding subsequent entries. */\n");
+ fprintf(file, "\t\tmach_msg_type_number_t i;\n");
+ fprintf(file, "\t\tfor(i = %s; i > 0; i--) {\n", arg->argCount->argVarName);
+ fprintf(file, "\t\t\tmach_port_name_t tmp_port_name = %sP[i - 1];\n", arg->argVarName);
+ fprintf(file, "\t\t\t/* Clear the whole message with zeros. */\n");
+ fprintf(file, "\t\t\tOutP->%s[i - 1].kernel_port_do_not_use = 0;\n", arg->argMsgField);
+ fprintf(file, "\t\t\tOutP->%s[i - 1].name = tmp_port_name;\n", arg->argMsgField, arg->argVarName);
+ fprintf(file, "\t\t}\n");
+ }
fprintf(file, "\t}\n");
}
}
diff --git a/type.c b/type.c
index c46f8f8..aaa01f9 100644
--- a/type.c
+++ b/type.c
@@ -121,6 +121,7 @@ itAlloc(void)
false, /* bool itString */
false, /* bool itVarArray */
false, /* bool itIndefinite */
+ false, /* bool itUserlandPort */
false, /* bool itKernelPort */
itNULL, /* ipc_type_t *itElement */
strNULL, /* identifier_t itUserType */
@@ -195,6 +196,15 @@ itCalculateSizeInfo(ipc_type_t *it)
warn("sizeof(%s) == 0", it->itName);
}
+static bool
+itIsPortType(ipc_type_t *it)
+{
+ return ((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) &&
+ (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)) ||
+ MACH_MSG_TYPE_PORT_ANY(it->itInName) ||
+ MACH_MSG_TYPE_PORT_ANY(it->itOutName);
+}
+
/*
* Fill in default values for some fields used in code generation:
* itInNameStr, itOutNameStr, itUserType, itServerType, itTransType
@@ -213,6 +223,10 @@ itCalculateNameInfo(ipc_type_t *it)
if (it->itServerType == strNULL)
it->itServerType = it->itName;
+ bool isPortType = itIsPortType(it);
+ bool isServerPort = isPortType && streql(it->itServerType, "mach_port_t");
+ bool isUserPort = isPortType && streql(it->itUserType, "mach_port_t");
+
/*
* KernelServer and KernelUser interfaces get special treatment here.
* On the kernel side of the interface, ports are really internal
@@ -226,25 +240,23 @@ itCalculateNameInfo(ipc_type_t *it)
* hand-conditionalizing on KERNEL_SERVER and KERNEL_USER.
*/
- if (IsKernelServer &&
- streql(it->itServerType, "mach_port_t") &&
- (((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) &&
- (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)) ||
- MACH_MSG_TYPE_PORT_ANY(it->itInName) ||
- MACH_MSG_TYPE_PORT_ANY(it->itOutName))) {
+ if (IsKernelServer && isServerPort) {
it->itServerType = "ipc_port_t";
it->itKernelPort = true;
- } else if (IsKernelUser &&
- streql(it->itUserType, "mach_port_t") &&
- (((it->itInName == MACH_MSG_TYPE_POLYMORPHIC) &&
- (it->itOutName == MACH_MSG_TYPE_POLYMORPHIC)) ||
- MACH_MSG_TYPE_PORT_ANY(it->itInName) ||
- MACH_MSG_TYPE_PORT_ANY(it->itOutName))) {
+ } else if (IsKernelUser && isUserPort) {
it->itUserType = "ipc_port_t";
it->itKernelPort = true;
} else
it->itKernelPort = false;
+ /*
+ * In 64 bits, ports are inlined as 8 bytes even though mach_port_t or
+ * mach_port_name_t are always 4 bytes. We do this to avoid slow message
+ * resizing inside the gnumach by ensuring inlined port names in messages
+ * are always 8 bytes long.
+ */
+ it->itUserlandPort = isPortType && !IsKernelUser && !IsKernelServer;
+
if (it->itTransType == strNULL)
it->itTransType = it->itServerType;
}
diff --git a/type.h b/type.h
index 1e4e49f..a34c978 100644
--- a/type.h
+++ b/type.h
@@ -133,6 +133,10 @@ typedef enum dealloc {
* itKernelPort is used only on kernel interfaces and is set to true when
* the initial type is mach_port_t, which in turn is actually translated to
* internal port pointers (ipc_port_t).
+ *
+ * itUserlandPort indicates that the field represents a port right (represented
+ * as a port name) and thus will only be true for userland stubs. This is
+ * used to change how inlined port names in messages are generated.
*/
typedef struct ipc_type
@@ -163,6 +167,7 @@ typedef struct ipc_type
bool itString;
bool itVarArray;
bool itIndefinite;
+ bool itUserlandPort;
bool itKernelPort;
struct ipc_type *itElement; /* may be NULL */
diff --git a/user.c b/user.c
index e044b4f..d98ab98 100644
--- a/user.c
+++ b/user.c
@@ -424,6 +424,7 @@ WritePackArgValue(FILE *file, const argument_t *arg)
const argument_t *count = arg->argCount;
const char *countRef = count->argByReferenceUser ? "*" :"";
const ipc_type_t *btype = it->itElement;
+ const bool is_64bit_port = IS_64BIT_ABI && btype->itUserlandPort;
/* Note btype->itNumber == count->argMultiplier */
@@ -434,6 +435,15 @@ WritePackArgValue(FILE *file, const argument_t *arg)
fprintf(file, "\t\tInP->%s%s.msgt_inline = FALSE;\n",
arg->argTTName,
arg->argLongForm ? ".msgtl_header" : "");
+ if (is_64bit_port) {
+ /* Update size of the type to be the same as a port name since
+ * we are passing port names out of line. */
+ fprintf(file, "\t\t/* We are passing mach_port_name_t out of line. */\n");
+ fprintf(file, "\t\tInP->%s%s.msgt_size = %d;\n",
+ arg->argTTName,
+ arg->argLongForm ? ".msgtl_header" : "",
+ port_name_size_in_bits);
+ }
if (arg->argDeallocate == d_YES)
fprintf(file, "\t\tInP->%s%s.msgt_deallocate = TRUE;\n",
arg->argTTName,
@@ -456,22 +466,38 @@ WritePackArgValue(FILE *file, const argument_t *arg)
fprintf(file, "\t}\n\telse if (%s%s) {\n", countRef, count->argVarName);
- fprintf(file, "\t\tmemcpy(InP->%s, %s%s, ", arg->argMsgField,
- ref, arg->argVarName);
- if (btype->itTypeSize > 1)
- fprintf(file, "%d * ", btype->itTypeSize);
- fprintf(file, "%s%s);\n",
- countRef, count->argVarName);
+ if (is_64bit_port) {
+ /* When copying inlined ports, the 64bit ABI uses 8 bytes to store port names,
+ * hence we cannot use memcpy directly.
+ */
+ fprintf(file, "\t\t/* Transform mach_port_name_t into mach_port_name_inlined_t. */\n");
+ fprintf(file, "\t\tmach_port_name_inlined_t *inlined_%s = (mach_port_name_inlined_t *)InP->%s;\n",
+ arg->argMsgField, arg->argMsgField);
+ fprintf(file, "\t\tmach_msg_type_number_t i;\n");
+ fprintf(file, "\t\tfor (i = 0; i < %s%s; i++) {\n", countRef, count->argVarName);
+ fprintf(file, "\t\t\t/* Clear the whole message with zeros. */\n");
+ fprintf(file, "\t\t\tinlined_%s[i].kernel_port_do_not_use = 0;\n",
+ arg->argMsgField);
+ fprintf(file, "\t\t\tinlined_%s[i].name = (%s%s)[i];\n", arg->argMsgField, ref, arg->argMsgField);
+ fprintf(file, "\t\t}\n");
+ } else {
+ fprintf(file, "\t\tmemcpy(InP->%s, %s%s, ", arg->argMsgField, ref, arg->argVarName);
+ if (btype->itTypeSize > 1)
+ fprintf(file, "%d * ", btype->itTypeSize);
+ fprintf(file, "%s%s);\n", countRef, count->argVarName);
+ }
fprintf(file, "\t}\n");
}
}
- else if (arg->argMultiplier > 1)
+ else if (arg->argMultiplier > 1) {
WriteCopyType(file, it, "InP->%s", "/* %s */ %d * %s%s",
arg->argMsgField, arg->argMultiplier,
ref, arg->argVarName);
- else
- WriteCopyType(file, it, "InP->%s", "/* %s */ %s%s",
- arg->argMsgField, ref, arg->argVarName);
+ } else {
+ bool is_inlined_port = it->itUserlandPort && it->itInLine;
+ WriteCopyType(file, it, "InP->%s%s", "/* %s%s */ %s%s",
+ arg->argMsgField, is_inlined_port ? ".name" : "", ref, arg->argVarName);
+ }
fprintf(file, "\n");
}
@@ -804,10 +830,23 @@ WriteTypeCheck(FILE *file, const argument_t *arg)
arg->argTTName,
arg->argLongForm ? "l" : "",
it->itNumber);
- fprintf(file, "\t (OutP->%s.msgt%s_size != %d)))\n",
- arg->argTTName,
- arg->argLongForm ? "l" : "",
- it->itSize);
+ if (IS_64BIT_ABI && it->itUserlandPort && arg->argLongForm) {
+ /* 64 bit inlined ports are 8 bytes long but we use mach_port_name_t when passing them out of line. */
+ fprintf(file, "\t (OutP->%s.msgtl_size != %d && OutP->%s.msgtl_header.msgt_inline == TRUE) || \n",
+ arg->argTTName,
+ it->itSize,
+ arg->argTTName);
+ fprintf(file, "\t (OutP->%s.msgtl_size != %d && OutP->%s.msgtl_header.msgt_inline == FALSE)",
+ arg->argTTName,
+ port_name_size_in_bits,
+ arg->argTTName);
+ } else {
+ fprintf(file, "\t (OutP->%s.msgt%s_size != %d)",
+ arg->argTTName,
+ arg->argLongForm ? "l" : "",
+ it->itSize);
+ }
+ fprintf(file, "))\n");
}
WriteMsgError(file, rt, "MIG_TYPE_ERROR");
fprintf(file, "#endif\t/* TypeCheck */\n");
@@ -907,6 +946,31 @@ WriteCheckMsgSize(FILE *file, const argument_t *arg)
fprintf(file, "\n");
}
+static void
+WriteExtractArgValueThroughCopy(FILE *file, const argument_t *arg, const argument_t *count,
+ const ipc_type_t *btype, const char *ref, const bool is_64bit_port)
+{
+ if (is_64bit_port) {
+ /* When copying inlined ports, the 64bit ABI uses 8 bytes to store port names,
+ * hence we cannot use memcpy.
+ */
+ fprintf(file, "\t\t/* Transform mach_port_name_inlined_t into mach_port_name_t. */\n");
+ fprintf(file, "\t\tmach_port_name_inlined_t *inlined_%s = (mach_port_name_inlined_t *)OutP->%s;\n",
+ arg->argMsgField, arg->argMsgField);
+ fprintf(file, "\t\tmach_msg_type_number_t i;\n");
+ fprintf(file, "\t\tfor (i = 0; i < OutP->%s; i++) {\n", count->argMsgField);
+ fprintf(file, "\t\t\t(%s%s)[i] = inlined_%s[i].name;\n",
+ ref, arg->argVarName, arg->argMsgField);
+ fprintf(file, "\t\t}\n");
+ } else {
+ fprintf(file, "\t\tmemcpy(%s%s, OutP->%s, ", ref, arg->argVarName,
+ arg->argMsgField);
+ if (btype->itTypeSize != btype->itNumber)
+ fprintf(file, "%d * ", btype->itTypeSize/btype->itNumber);
+ fprintf(file, "OutP->%s);\n", count->argMsgField);
+ }
+}
+
/*************************************************************
* Write code to copy an argument from the reply message
* to the parameter. Called by WriteRoutine for each argument
@@ -944,11 +1008,12 @@ WriteExtractArgValue(FILE *file, const argument_t *arg)
const argument_t *count = arg->argCount;
const char *countRef = count->argByReferenceUser ? "*" : "";
const ipc_type_t *btype = argType->itElement;
+ const bool is_64bit_port = IS_64BIT_ABI && btype->itUserlandPort;
fprintf(file, "\tif (!OutP->%s%s.msgt_inline)\n",
arg->argTTName,
arg->argLongForm ? ".msgtl_header" : "");
- fprintf(file, "\t %s%s = OutP->%s%s;\n",
+ fprintf(file, "\t\t%s%s = OutP->%s%s;\n",
ref, arg->argVarName,
arg->argMsgField,
OOLPostfix);
@@ -956,24 +1021,18 @@ WriteExtractArgValue(FILE *file, const argument_t *arg)
if (btype->itNumber > 1)
fprintf(file, " / %d", btype->itNumber);
fprintf(file, " > %s%s) {\n", countRef, count->argVarName);
- fprintf(file, "\t %smig_allocate((vm_offset_t *)%s,\n\t\t",
+ fprintf(file, "\t\t%smig_allocate((vm_offset_t *)%s, ",
SubrPrefix, arg->argVarName); /* no ref! */
- if (btype->itTypeSize != btype->itNumber)
- fprintf(file, "%d * ", btype->itTypeSize/btype->itNumber);
- fprintf(file, "OutP->%s);\n", count->argMsgField);
- fprintf(file, "\t memcpy(%s%s, OutP->%s, ", ref, arg->argVarName,
- arg->argMsgField);
- if (btype->itTypeSize != btype->itNumber)
+ if (is_64bit_port)
+ fprintf(file, "%d * ", port_name_size);
+ else if (btype->itTypeSize != btype->itNumber)
fprintf(file, "%d * ", btype->itTypeSize/btype->itNumber);
fprintf(file, "OutP->%s);\n", count->argMsgField);
+ WriteExtractArgValueThroughCopy(file, arg, count, btype, ref, is_64bit_port);
fprintf(file, "\t}\n");
fprintf(file, "\telse if (OutP->%s) {\n", count->argMsgField);
- fprintf(file, "\t memcpy(%s%s, OutP->%s, ", ref, arg->argVarName,
- arg->argMsgField);
- if (btype->itTypeSize != btype->itNumber)
- fprintf(file, "%d * ", btype->itTypeSize/btype->itNumber);
- fprintf(file, "OutP->%s);\n", count->argMsgField);
+ WriteExtractArgValueThroughCopy(file, arg, count, btype, ref, is_64bit_port);
fprintf(file, "\t}\n");
}
else {
@@ -1025,15 +1084,17 @@ WriteExtractArgValue(FILE *file, const argument_t *arg)
fprintf(file, "\t}\n");
}
}
- else if (arg->argMultiplier > 1)
+ else if (arg->argMultiplier > 1) {
WriteCopyType(file, argType,
"%s%s", "/* %s%s */ OutP->%s / %d",
ref, arg->argVarName, arg->argMsgField,
arg->argMultiplier);
- else
+ } else {
+ bool is_inlined_port = argType->itUserlandPort && argType->itInLine;
WriteCopyType(file, argType,
- "%s%s", "/* %s%s */ OutP->%s",
- ref, arg->argVarName, arg->argMsgField);
+ "%s%s", "/* %s%s */ OutP->%s%s",
+ ref, arg->argVarName, arg->argMsgField, is_inlined_port ? ".name" : "");
+ }
fprintf(file, "\n");
}
diff --git a/utils.c b/utils.c
index ec0f2d1..0d69cb2 100644
--- a/utils.c
+++ b/utils.c
@@ -317,6 +317,9 @@ WriteFieldDeclPrim(FILE *file, const argument_t *arg,
if (it->itInLine && it->itVarArray)
{
ipc_type_t *btype = it->itElement;
+ identifier_t original_type_name = (*tfunc)(btype);
+ identifier_t inlined_type_name = btype->itUserlandPort ?
+ "mach_port_name_inlined_t" : original_type_name;
/*
* Build our own declaration for a varying array:
@@ -325,19 +328,27 @@ WriteFieldDeclPrim(FILE *file, const argument_t *arg,
*/
fprintf(file, "\t\tunion {\n");
fprintf(file, "\t\t\t%s %s[%d];\n",
- (*tfunc)(btype),
+ inlined_type_name,
arg->argMsgField,
it->itNumber/btype->itNumber);
fprintf(file, "\t\t\t%s%s *%s%s;\n",
tfunc == FetchUserType && UserVarConst(arg)
? "const " : "",
- (*tfunc)(btype),
+ original_type_name,
arg->argMsgField,
OOLPostfix);
fprintf(file, "\t\t};");
}
else
- fprintf(file, "\t\t%s %s;", (*tfunc)(it), arg->argMsgField);
+ {
+ identifier_t original_type_name = (*tfunc)(it);
+ identifier_t final_type_name = it->itUserlandPort && it->itInLine ?
+ "mach_port_name_inlined_t" : original_type_name;
+
+ fprintf(file, "\t\t%s %s;",
+ final_type_name,
+ arg->argMsgField);
+ }
if (it->itPadSize != 0)
fprintf(file, "\n\t\tchar %s[%d];", arg->argPadName, it->itPadSize);
@@ -366,7 +377,11 @@ WriteStaticLongDecl(FILE *file, const ipc_type_t *it,
* so we fill mach_msg_type_long_t just like mach_msg_type_t.
*/
fprintf(file, "\t\t\t.msgt_name =\t\t(unsigned char) %s,\n", msgt_name);
- fprintf(file, "\t\t\t.msgt_size =\t\t%d,\n", it->itSize);
+ /* In case we are passing out of line ports, we always send as a contiguous array of port names
+ * rather than mach_port_name_inlined_t. */
+ const u_int true_size = (it->itUserlandPort && !it->itInLine && it->itNumber == 0) ?
+ port_name_size_in_bits : it->itSize;
+ fprintf(file, "\t\t\t.msgt_size =\t\t%d,\n", true_size);
fprintf(file, "\t\t\t.msgt_number =\t\t%d,\n", it->itNumber);
} else {
fprintf(file, "\t\t\t.msgt_name =\t\t0,\n");
@@ -407,10 +422,11 @@ WriteStaticShortDecl(FILE *file, const ipc_type_t *it,
fprintf(file, "\t};\n");
if (it->itInLine && !it->itVarArray) {
identifier_t type = is_server ? FetchServerType(it) : FetchUserType(it);
+ identifier_t actual_type = it->itUserlandPort ? "mach_port_name_inlined_t" : type;
const u_int size_bytes = it->itSize >> 3;
fprintf(file, "\t_Static_assert(sizeof(%s) == %d * %d, \"expected %s to be size %d * %d\");\n",
- type, size_bytes, it->itNumber,
- type, size_bytes, it->itNumber);
+ actual_type, size_bytes, it->itNumber,
+ actual_type, size_bytes, it->itNumber);
}
}