1/* 2 * Copyright (c) 1999-2009 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23/* 24 * @OSF_COPYRIGHT@ 25 */ 26/* 27 * Mach Operating System 28 * Copyright (c) 1991,1990 Carnegie Mellon University 29 * All Rights Reserved. 30 * 31 * Permission to use, copy, modify and distribute this software and its 32 * documentation is hereby granted, provided that both the copyright 33 * notice and this permission notice appear in all copies of the 34 * software, derivative works or modified versions, and any portions 35 * thereof, and that both notices appear in supporting documentation. 36 * 37 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 38 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 39 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 40 * 41 * Carnegie Mellon requests users of this software to return to 42 * 43 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 44 * School of Computer Science 45 * Carnegie Mellon University 46 * Pittsburgh PA 15213-3890 47 * 48 * any improvements or extensions that they make and grant Carnegie Mellon 49 * the rights to redistribute these changes. 50 */ 51 52#include <assert.h> 53#include <stdlib.h> 54 55#include <mach/message.h> 56#include "write.h" 57#include "utils.h" 58#include "global.h" 59#include "error.h" 60 61#ifndef max 62#define max(a,b) (((a) > (b)) ? (a) : (b)) 63#endif /* max */ 64 65void WriteLogDefines(); 66void WriteIdentificationString(); 67static void WriteFieldDecl(); 68 69static void 70WriteKPD_Iterator(FILE *file, boolean_t in, boolean_t varying, argument_t *arg, boolean_t bracket) 71{ 72 register ipc_type_t *it = arg->argType; 73 char string[MAX_STR_LEN]; 74 75 fprintf(file, "\t{\n"); 76 fprintf(file, "\t register\t%s\t*ptr;\n", it->itKPDType); 77 fprintf(file, "\t register int\ti"); 78 if (varying && !in) 79 fprintf(file, ", j"); 80 fprintf(file, ";\n\n"); 81 82 if (in) 83 sprintf(string, "In%dP", arg->argRequestPos); 84 else 85 sprintf(string, "OutP"); 86 87 fprintf(file, "\t ptr = &%s->%s[0];\n", string, arg->argMsgField); 88 89 if (varying) { 90 register argument_t *count = arg->argCount; 91 92 if (in) 93 fprintf(file, "\t for (i = 0; i < In%dP->%s; ptr++, i++) %s\n", count->argRequestPos, count->argMsgField, (bracket) ? "{" : ""); 94 else { 95 fprintf(file, "\t j = min(%d, ", it->itKPD_Number); 96 if (akCheck(count->argKind, akbVarNeeded)) 97 fprintf(file, "%s);\n", count->argName); 98 else 99 fprintf(file, "%s->%s);\n", string, count->argMsgField); 100 fprintf(file, "\t for (i = 0; i < j; ptr++, i++) %s\n", (bracket) ? "{" : ""); 101 } 102} 103 else 104 fprintf(file, "\t for (i = 0; i < %d; ptr++, i++) %s\n", it->itKPD_Number, (bracket) ? "{" : ""); 105} 106 107static void 108WriteMyIncludes(FILE *file, statement_t *stats) 109{ 110 if (ServerHeaderFileName == strNULL || UseSplitHeaders) 111 WriteIncludes(file, FALSE, FALSE); 112 if (ServerHeaderFileName != strNULL) 113 { 114 register char *cp; 115 116 /* Strip any leading path from ServerHeaderFileName. */ 117 cp = strrchr(ServerHeaderFileName, '/'); 118 if (cp == 0) 119 cp = ServerHeaderFileName; 120 else 121 cp++; /* skip '/' */ 122 fprintf(file, "#include \"%s\"\n", cp); 123 } 124 if (ServerHeaderFileName == strNULL || UseSplitHeaders) 125 WriteImplImports(file, stats, FALSE); 126 if (UseEventLogger) { 127 if (IsKernelServer) { 128 fprintf(file, "#if\t__MigKernelSpecificCode\n"); 129 fprintf(file, "#include <mig_debug.h>\n"); 130 fprintf(file, "#endif\t/* __MigKernelSpecificCode */\n"); 131 } 132 fprintf(file, "#if MIG_DEBUG\n"); 133 fprintf(file, "#include <mach/mig_log.h>\n"); 134 fprintf(file, "#endif /* MIG_DEBUG */\n"); 135 } 136 137 fprintf(file, "\n"); 138} 139 140static void 141WriteGlobalDecls(FILE *file) 142{ 143 if (BeAnsiC) { 144 fprintf(file, "#define novalue void\n"); 145 } 146 else { 147 fprintf(file, "#if\t%s\n", NewCDecl); 148 fprintf(file, "#define novalue void\n"); 149 fprintf(file, "#else\n"); 150 fprintf(file, "#define novalue int\n"); 151 fprintf(file, "#endif\t/* %s */\n", NewCDecl); 152 } 153 fprintf(file, "\n"); 154 155 if (RCSId != strNULL) 156 WriteRCSDecl(file, strconcat(SubsystemName, "_server"), RCSId); 157 158 /* Used for locations in the request message, *not* reply message. 159 Reply message locations aren't dependent on IsKernelServer. */ 160 161 if (IsKernelServer) { 162 fprintf(file, "#if\t__MigKernelSpecificCode\n"); 163 fprintf(file, "#define msgh_request_port\tmsgh_remote_port\n"); 164 fprintf(file, "#define MACH_MSGH_BITS_REQUEST(bits)"); 165 fprintf(file, "\tMACH_MSGH_BITS_REMOTE(bits)\n"); 166 fprintf(file, "#define msgh_reply_port\t\tmsgh_local_port\n"); 167 fprintf(file, "#define MACH_MSGH_BITS_REPLY(bits)"); 168 fprintf(file, "\tMACH_MSGH_BITS_LOCAL(bits)\n"); 169 fprintf(file, "#else\n"); 170 } 171 fprintf(file, "#define msgh_request_port\tmsgh_local_port\n"); 172 fprintf(file, "#define MACH_MSGH_BITS_REQUEST(bits)"); 173 fprintf(file, "\tMACH_MSGH_BITS_LOCAL(bits)\n"); 174 fprintf(file, "#define msgh_reply_port\t\tmsgh_remote_port\n"); 175 fprintf(file, "#define MACH_MSGH_BITS_REPLY(bits)"); 176 fprintf(file, "\tMACH_MSGH_BITS_REMOTE(bits)\n"); 177 if (IsKernelServer) { 178 fprintf(file, "#endif /* __MigKernelSpecificCode */\n"); 179 } 180 fprintf(file, "\n"); 181 if (UseEventLogger) 182 WriteLogDefines(file, "MACH_MSG_LOG_SERVER"); 183 fprintf(file, "#define MIG_RETURN_ERROR(X, code)\t{\\\n"); 184 fprintf(file, "\t\t\t\t((mig_reply_error_t *)X)->RetCode = code;\\\n"); 185 fprintf(file, "\t\t\t\t((mig_reply_error_t *)X)->NDR = NDR_record;\\\n"); 186 fprintf(file, "\t\t\t\treturn;\\\n"); 187 fprintf(file, "\t\t\t\t}\n"); 188 fprintf(file, "\n"); 189} 190 191 192static void 193WriteForwardDeclarations(FILE *file, statement_t *stats) 194{ 195 register statement_t *stat; 196 197 fprintf(file, "/* Forward Declarations */\n\n"); 198 for (stat = stats; stat != stNULL; stat = stat->stNext) 199 if (stat->stKind == skRoutine) { 200 fprintf(file, "\nmig_internal novalue _X%s\n", stat->stRoutine->rtName); 201 fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);\n"); 202 } 203 fprintf(file, "\n"); 204} 205 206static void 207WriteMIGCheckDefines(FILE *file) 208{ 209 fprintf(file, "#define\t__MIG_check__Request__%s_subsystem__ 1\n", SubsystemName); 210 fprintf(file, "\n"); 211} 212 213static void 214WriteNDRDefines(FILE *file) 215{ 216 fprintf(file, "#define\t__NDR_convert__Request__%s_subsystem__ 1\n", SubsystemName); 217 fprintf(file, "\n"); 218} 219 220static void 221WriteProlog(FILE *file, statement_t *stats) 222{ 223 WriteIdentificationString(file); 224 fprintf(file, "\n"); 225 fprintf(file, "/* Module %s */\n", SubsystemName); 226 fprintf(file, "\n"); 227 WriteMIGCheckDefines(file); 228 if (CheckNDR) 229 WriteNDRDefines(file); 230 WriteMyIncludes(file, stats); 231 WriteBogusDefines(file); 232 WriteApplDefaults(file, "Rcv"); 233 WriteGlobalDecls(file); 234 if (ServerHeaderFileName == strNULL) { 235 WriteRequestTypes(file, stats); 236 WriteReplyTypes(file, stats); 237 WriteServerReplyUnion(file, stats); 238 } 239} 240 241static void 242WriteSymTabEntries(FILE *file, statement_t *stats) 243{ 244 register statement_t *stat; 245 register u_int current = 0; 246 247 for (stat = stats; stat != stNULL; stat = stat->stNext) 248 if (stat->stKind == skRoutine) { 249 register int num = stat->stRoutine->rtNumber; 250 char *name = stat->stRoutine->rtName; 251 while (++current <= num) 252 fprintf(file,"\t\t\t{ \"\", 0, 0 },\n"); 253 fprintf(file, "\t{ \"%s\", %d, _X%s },\n", name, SubsystemBase + current - 1, name); 254 } 255 while (++current <= rtNumber) 256 fprintf(file,"\t{ \"\", 0, 0 },\n"); 257} 258 259static void 260WriteRoutineEntries(FILE *file, statement_t *stats) 261{ 262 register u_int current = 0; 263 register statement_t *stat; 264 char *sig_array, *rt_name; 265 int arg_count, descr_count; 266 int offset = 0; 267 size_t serverSubsysNameLen = strlen(ServerSubsys); 268 269 fprintf(file, "\t{\n"); 270 for (stat = stats; stat != stNULL; stat = stat->stNext) 271 if (stat->stKind == skRoutine) { 272 register routine_t *rt = stat->stRoutine; 273 size_t rtNameLen = strlen(rt->rtName); 274 275 // Include length of rt->rtName in calculation of necessary buffer size, since that string 276 // is actually written into the buffer along with the Server Subsystem name. 277 sig_array = (char *) malloc(serverSubsysNameLen + rtNameLen + 80); 278 rt_name = (char *) malloc(rtNameLen + 5); 279 while (current++ < rt->rtNumber) 280 fprintf(file, "\t\t{0, 0, 0, 0, 0, 0},\n"); 281 // NOTE: if either of the two string constants in the sprintf() function calls below get 282 // much longer, be sure to increase the constant '80' (in the first malloc() call) to ensure 283 // that the allocated buffer is large enough. (Currently, I count 66 characters in the first 284 // string constant, 65 in the second. 80 ought to be enough for now...) 285 if (UseRPCTrap) { 286 sprintf(sig_array, "&%s.arg_descriptor[%d], (mach_msg_size_t)sizeof(__Reply__%s_t)", ServerSubsys, offset, rt->rtName); 287 } 288 else { 289 sprintf(sig_array, "(routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__%s_t)", rt->rtName); 290 } 291 sprintf(rt_name, "_X%s", rt->rtName); 292 descr_count = rtCountArgDescriptors(rt->rtArgs, &arg_count); 293 offset += descr_count; 294 WriteRPCRoutineDescriptor(file, rt, arg_count, (UseRPCTrap) ? descr_count : 0, rt_name, sig_array); 295 fprintf(file, ",\n"); 296 free(sig_array); 297 free(rt_name); 298 } 299 while (current++ < rtNumber) 300 fprintf(file, "\t\t{0, 0, 0, 0, 0, 0},\n"); 301 302 fprintf(file, "\t}"); 303} 304 305static void 306WriteArgDescriptorEntries(FILE *file, statement_t *stats) 307{ 308 register statement_t *stat; 309 310 fprintf(file, ",\n\n\t{\n"); 311 for (stat = stats; stat != stNULL; stat = stat->stNext) 312 if (stat->stKind == skRoutine) { 313 register routine_t *rt = stat->stRoutine; 314 315 /* For each arg of the routine, write an arg descriptor: 316 */ 317 WriteRPCRoutineArgDescriptor(file, rt); 318 } 319 fprintf(file, "\t},\n\n"); 320} 321 322 323/* 324 * Write out the description of this subsystem, for use in direct RPC 325 */ 326static void 327WriteSubsystem(FILE *file, statement_t *stats) 328{ 329 register statement_t *stat; 330 int descr_count = 0; 331 332 for (stat = stats; stat != stNULL; stat = stat->stNext) 333 if (stat->stKind == skRoutine) { 334 register routine_t *rt = stat->stRoutine; 335 descr_count += rtCountArgDescriptors(rt->rtArgs, (int *) 0); 336 } 337 fprintf(file, "\n"); 338 if (ServerHeaderFileName == strNULL) { 339 WriteMigExternal(file); 340 fprintf(file, "boolean_t %s(", ServerDemux); 341 if (BeAnsiC) { 342 fprintf(file, "\n\t\tmach_msg_header_t *InHeadP,"); 343 fprintf(file, "\n\t\tmach_msg_header_t *OutHeadP"); 344 } 345 fprintf(file, ");\n\n"); 346 347 WriteMigExternal(file); 348 fprintf(file, "mig_routine_t %s_routine(", ServerDemux); 349 if (BeAnsiC) { 350 fprintf(file, "\n\t\tmach_msg_header_t *InHeadP"); 351 } 352 fprintf(file, ");\n\n"); 353 } 354 fprintf(file, "\n/* Description of this subsystem, for use in direct RPC */\n"); 355 if (ServerHeaderFileName == strNULL) { 356 fprintf(file, "const struct %s {\n", ServerSubsys); 357 if (UseRPCTrap) { 358 fprintf(file, "\tstruct subsystem *\tsubsystem;\t/* Reserved for system use */\n"); 359 } 360 else { 361 fprintf(file, "\tmig_server_routine_t \tserver;\t/* Server routine */\n"); 362 } 363 fprintf(file, "\tmach_msg_id_t\tstart;\t/* Min routine number */\n"); 364 fprintf(file, "\tmach_msg_id_t\tend;\t/* Max routine number + 1 */\n"); 365 fprintf(file, "\tunsigned int\tmaxsize;\t/* Max msg size */\n"); 366 if (UseRPCTrap) { 367 fprintf(file, "\tvm_address_t\tbase_addr;\t/* Base address */\n"); 368 fprintf(file, "\tstruct rpc_routine_descriptor\t/*Array of routine descriptors */\n"); 369 } 370 else { 371 fprintf(file, "\tvm_address_t\treserved;\t/* Reserved */\n"); 372 fprintf(file, "\tstruct routine_descriptor\t/*Array of routine descriptors */\n"); 373 } 374 fprintf(file, "\t\troutine[%d];\n", rtNumber); 375 if (UseRPCTrap) { 376 fprintf(file, "\tstruct rpc_routine_arg_descriptor\t/*Array of arg descriptors */\n"); 377 fprintf(file, "\t\targ_descriptor[%d];\n", descr_count); 378 } 379 fprintf(file, "} %s = {\n", ServerSubsys); 380 } 381 else { 382 fprintf(file, "const struct %s %s = {\n", ServerSubsys, ServerSubsys); 383 } 384 if (UseRPCTrap) { 385 fprintf(file, "\t0,\n"); 386 } 387 else { 388 fprintf(file, "\t%s_routine,\n", ServerDemux); 389 } 390 fprintf(file, "\t%d,\n", SubsystemBase); 391 fprintf(file, "\t%d,\n", SubsystemBase + rtNumber); 392 fprintf(file, "\t(mach_msg_size_t)sizeof(union __ReplyUnion__%s),\n", ServerSubsys); 393 if (UseRPCTrap) { 394 fprintf(file, "\t(vm_address_t)&%s,\n", ServerSubsys); 395 } 396 else { 397 fprintf(file, "\t(vm_address_t)0,\n"); 398 } 399 WriteRoutineEntries(file, stats); 400 401 if (UseRPCTrap) 402 WriteArgDescriptorEntries(file, stats); 403 else 404 fprintf(file, "\n"); 405 406 fprintf(file, "};\n\n"); 407} 408 409#if NOT_CURRENTLY_USED 410 411static void 412WriteArraySizes(FILE *file, statement_t *stats) 413{ 414 register u_int current = 0; 415 register statement_t *stat; 416 417 for (stat = stats; stat != stNULL; stat = stat->stNext) 418 if (stat->stKind == skRoutine) { 419 register routine_t *rt = stat->stRoutine; 420 421 while (current++ < rt->rtNumber) 422 fprintf(file, "\t\t0,\n"); 423 fprintf(file, "\t\t(mach_msg_size_t)sizeof(__Reply__%s_t),\n", rt->rtName); 424 } 425 while (current++ < rtNumber) 426 fprintf(file, "\t\t\t0,\n"); 427} 428 429#endif /* NOT_CURRENTLY_USED */ 430 431void 432WriteServerRequestUnion(FILE *file, statement_t *stats) 433{ 434 register statement_t *stat; 435 436 fprintf(file, "\n"); 437 fprintf(file, "/* union of all requests */\n\n"); 438 fprintf(file, "#ifndef __RequestUnion__%s__defined\n", ServerSubsys); 439 fprintf(file, "#define __RequestUnion__%s__defined\n", ServerSubsys); 440 fprintf(file, "union __RequestUnion__%s {\n", ServerSubsys); 441 for (stat = stats; stat != stNULL; stat = stat->stNext) { 442 if (stat->stKind == skRoutine) { 443 register routine_t *rt; 444 445 rt = stat->stRoutine; 446 fprintf(file, "\t__Request__%s_t Request_%s;\n", rt->rtName, rt->rtName); 447 } 448 } 449 fprintf(file, "};\n"); 450 fprintf(file, "#endif /* __RequestUnion__%s__defined */\n", ServerSubsys); 451} 452 453void 454WriteServerReplyUnion(FILE *file, statement_t *stats) 455{ 456 register statement_t *stat; 457 458 fprintf(file, "\n"); 459 fprintf(file, "/* union of all replies */\n\n"); 460 fprintf(file, "#ifndef __ReplyUnion__%s__defined\n", ServerSubsys); 461 fprintf(file, "#define __ReplyUnion__%s__defined\n", ServerSubsys); 462 fprintf(file, "union __ReplyUnion__%s {\n", ServerSubsys); 463 for (stat = stats; stat != stNULL; stat = stat->stNext) { 464 if (stat->stKind == skRoutine) { 465 register routine_t *rt; 466 467 rt = stat->stRoutine; 468 fprintf(file, "\t__Reply__%s_t Reply_%s;\n", rt->rtName, rt->rtName); 469 } 470 } 471 fprintf(file, "};\n"); 472 fprintf(file, "#endif /* __RequestUnion__%s__defined */\n", ServerSubsys); 473} 474 475static void 476WriteDispatcher(FILE *file, statement_t *stats) 477{ 478 /* 479 * Write the subsystem stuff. 480 */ 481 fprintf(file, "\n"); 482 WriteSubsystem(file, stats); 483 484 /* 485 * Then, the server routine 486 */ 487 fprintf(file, "mig_external boolean_t %s\n", ServerDemux); 488 if (BeAnsiC) { 489 fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n"); 490 } 491 else { 492 fprintf(file, "#if\t%s\n", NewCDecl); 493 fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n"); 494 fprintf(file, "#else\n"); 495 fprintf(file, "\t(InHeadP, OutHeadP)\n"); 496 fprintf(file, "\tmach_msg_header_t *InHeadP, *OutHeadP;\n"); 497 fprintf(file, "#endif\t/* %s */\n", NewCDecl); 498 } 499 500 fprintf(file, "{\n"); 501 fprintf(file, "\t/*\n"); 502 fprintf(file, "\t * typedef struct {\n"); 503 fprintf(file, "\t * \tmach_msg_header_t Head;\n"); 504 fprintf(file, "\t * \tNDR_record_t NDR;\n"); 505 fprintf(file, "\t * \tkern_return_t RetCode;\n"); 506 fprintf(file, "\t * } mig_reply_error_t;\n"); 507 fprintf(file, "\t */\n"); 508 fprintf(file, "\n"); 509 510 fprintf(file, "\tregister mig_routine_t routine;\n"); 511 fprintf(file, "\n"); 512 513 fprintf(file, "\tOutHeadP->msgh_bits = "); 514 fprintf(file, "MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InHeadP->msgh_bits), 0);\n"); 515 fprintf(file, "\tOutHeadP->msgh_remote_port = InHeadP->msgh_reply_port;\n"); 516 fprintf(file, "\t/* Minimal size: routine() will update it if different */\n"); 517 fprintf(file, "\tOutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t);\n"); 518 fprintf(file, "\tOutHeadP->msgh_local_port = MACH_PORT_NULL;\n"); 519 fprintf(file, "\tOutHeadP->msgh_id = InHeadP->msgh_id + 100;\n"); 520 fprintf(file, "\n"); 521 522 fprintf(file, "\tif ((InHeadP->msgh_id > %d) || (InHeadP->msgh_id < %d) ||\n", SubsystemBase + rtNumber - 1, SubsystemBase); 523 fprintf(file, "\t ((routine = %s.routine[InHeadP->msgh_id - %d].stub_routine) == 0)) {\n", ServerSubsys, SubsystemBase); 524 fprintf(file, "\t\t((mig_reply_error_t *)OutHeadP)->NDR = NDR_record;\n"); 525 fprintf(file, "\t\t((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID;\n"); 526 if (UseEventLogger) { 527 fprintf(file, "#if MIG_DEBUG\n"); 528 fprintf(file, "\t\tLOG_ERRORS(MACH_MSG_LOG_SERVER, MACH_MSG_ERROR_UNKNOWN_ID,\n"); 529 fprintf(file, "\t\t\t&InHeadP->msgh_id, __FILE__, __LINE__);\n"); 530 fprintf(file, "#endif /* MIG_DEBUG */\n"); 531 } 532 fprintf(file, "\t\treturn FALSE;\n"); 533 fprintf(file, "\t}\n"); 534 535 /* Call appropriate routine */ 536 fprintf(file, "\t(*routine) (InHeadP, OutHeadP);\n"); 537 fprintf(file, "\treturn TRUE;\n"); 538 fprintf(file, "}\n"); 539 fprintf(file, "\n"); 540 541 /* 542 * Then, the <subsystem>_server_routine routine 543 */ 544 fprintf(file, "mig_external mig_routine_t %s_routine\n", ServerDemux); 545 if (BeAnsiC) { 546 fprintf(file, "\t(mach_msg_header_t *InHeadP)\n"); 547 } 548 else { 549 fprintf(file, "#if\t%s\n", NewCDecl); 550 fprintf(file, "\t(mach_msg_header_t *InHeadP)\n"); 551 fprintf(file, "#else\n"); 552 fprintf(file, "\t(InHeadP)\n"); 553 fprintf(file, "\tmach_msg_header_t *InHeadP;\n"); 554 fprintf(file, "#endif\t/* %s */\n", NewCDecl); 555 } 556 557 fprintf(file, "{\n"); 558 fprintf(file, "\tregister int msgh_id;\n"); 559 fprintf(file, "\n"); 560 fprintf(file, "\tmsgh_id = InHeadP->msgh_id - %d;\n", SubsystemBase); 561 fprintf(file, "\n"); 562 fprintf(file, "\tif ((msgh_id > %d) || (msgh_id < 0))\n", rtNumber - 1); 563 fprintf(file, "\t\treturn 0;\n"); 564 fprintf(file, "\n"); 565 fprintf(file, "\treturn %s.routine[msgh_id].stub_routine;\n", ServerSubsys); 566 fprintf(file, "}\n"); 567 568 /* symtab */ 569 570 if (GenSymTab) { 571 fprintf(file,"\nmig_symtab_t _%sSymTab[] = {\n",SubsystemName); 572 WriteSymTabEntries(file,stats); 573 fprintf(file,"};\n"); 574 fprintf(file,"int _%sSymTabBase = %d;\n",SubsystemName,SubsystemBase); 575 fprintf(file,"int _%sSymTabEnd = %d;\n",SubsystemName,SubsystemBase+rtNumber); 576 } 577} 578 579#if NOT_CURRENTLY_USED 580/* 581 * Returns the return type of the server-side work function. 582 * Suitable for "extern %s serverfunc()". 583 */ 584static char * 585ServerSideType(routine_t *rt) 586{ 587 return rt->rtRetCode->argType->itTransType; 588} 589#endif /* NOT_CURRENTLY_USED */ 590 591static void 592WriteRetCode(FILE *file, register argument_t *ret) 593{ 594 register ipc_type_t *it = ret->argType; 595 596 if (akCheck(ret->argKind, akbVarNeeded)) { 597 fprintf(file, "\t%s %s;\n", it->itTransType, ret->argVarName); 598 } 599} 600 601static void 602WriteLocalVarDecl(FILE *file, register argument_t *arg) 603{ 604 register ipc_type_t *it = arg->argType; 605 register ipc_type_t *btype = it->itElement; 606 607 if (IS_VARIABLE_SIZED_UNTYPED(it)) 608 fprintf(file, "\t%s %s[%d]", btype->itTransType, arg->argVarName, btype->itNumber ? it->itNumber/btype->itNumber : 0); 609 else if (IS_MULTIPLE_KPD(it)) { 610 if (btype->itTransType != strNULL) 611 fprintf(file, "\t%s %s[%d]", btype->itTransType, arg->argVarName, it->itKPD_Number); 612 else 613 /* arrays of ool or oolport */ 614 fprintf(file, "\tvoid *%s[%d]", arg->argVarName, it->itKPD_Number); 615 } 616 else 617 fprintf(file, "\t%s %s", it->itTransType, arg->argVarName); 618} 619 620#if NOT_CURRENTLY_USED 621static void 622WriteServerArgDecl(FILE *file, argument_t *arg) 623{ 624 fprintf(file, "%s %s%s", arg->argType->itTransType, arg->argByReferenceServer ? "*" : "", arg->argVarName); 625} 626#endif /* NOT_CURRENTLY_USED */ 627 628/* 629 * Writes the local variable declarations which are always 630 * present: InP, OutP, the server-side work function. 631 */ 632static void 633WriteVarDecls(FILE *file, routine_t *rt) 634{ 635 int i; 636 637 fprintf(file, "\tRequest *In0P = (Request *) InHeadP;\n"); 638 for (i = 1; i <= rt->rtMaxRequestPos; i++) 639 fprintf(file, "\tRequest *In%dP;\n", i); 640 fprintf(file, "\tReply *OutP = (Reply *) OutHeadP;\n"); 641 642 /* if reply is variable, we may need msgh_size_delta and msgh_size */ 643 if (rt->rtNumReplyVar > 1) 644 fprintf(file, "\tunsigned int msgh_size;\n"); 645 if (rt->rtMaxReplyPos > 0) 646 fprintf(file, "\tunsigned int msgh_size_delta;\n"); 647 if (rt->rtNumReplyVar > 1 || rt->rtMaxReplyPos > 0) 648 fprintf(file, "\n"); 649 650 if (rt->rtServerImpl) { 651 fprintf(file, "\tmach_msg_max_trailer_t *TrailerP;\n"); 652 fprintf(file, "#if\t__MigTypeCheck\n"); 653 fprintf(file, "\tunsigned int trailer_size;\n"); 654 fprintf(file, "#endif\t/* __MigTypeCheck */\n"); 655 } 656 fprintf(file, "#ifdef\t__MIG_check__Request__%s_t__defined\n", rt->rtName); 657 fprintf(file, "\tkern_return_t check_result;\n"); 658 fprintf(file, "#endif\t/* __MIG_check__Request__%s_t__defined */\n", rt->rtName); 659 fprintf(file, "\n"); 660} 661 662static void 663WriteReplyInit(FILE *file, routine_t *rt) 664{ 665 fprintf(file, "\n"); 666 if (rt->rtNumReplyVar > 1 || rt->rtMaxReplyPos) 667 /* WritheAdjustMsgSize() has been executed at least once! */ 668 fprintf(file, "\tOutP = (Reply *) OutHeadP;\n"); 669 670 if (!rt->rtSimpleReply) /* complex reply message */ 671 fprintf(file, "\tOutP->Head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;\n"); 672 673 if (rt->rtNumReplyVar == 0) { 674 fprintf(file, "\tOutP->Head.msgh_size = "); 675 rtMinReplySize(file, rt, "Reply"); 676 fprintf(file, ";\n"); 677 } 678 else if (rt->rtNumReplyVar > 1) 679 fprintf(file, "\tOutP->Head.msgh_size = msgh_size;\n"); 680 /* the case rt->rtNumReplyVar = 1 is taken care of in WriteAdjustMsgSize() */ 681} 682 683static void 684WriteRetCArgCheckError(FILE *file, routine_t *rt) 685{ 686 fprintf(file, "\tif (!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&\n"); 687 fprintf(file, "\t (In0P->Head.msgh_size == (mach_msg_size_t)sizeof(mig_reply_error_t)))\n"); 688 fprintf(file, "\t{\n"); 689} 690 691static void 692WriteRetCArgFinishError(FILE *file, routine_t *rt) 693{ 694 argument_t *retcode = rt->rtRetCArg; 695 696 fprintf(file, "\treturn;\n"); 697 fprintf(file, "\t}\n"); 698 retcode->argMsgField = "KERN_SUCCESS"; 699} 700 701static void 702WriteCheckHead(FILE *file, routine_t *rt) 703{ 704 fprintf(file, "#if\t__MigTypeCheck\n"); 705 if (rt->rtNumRequestVar > 0) 706 fprintf(file, "\tmsgh_size = In0P->Head.msgh_size;\n"); 707 708 if (rt->rtSimpleRequest) { 709 /* Expecting a simple message. */ 710 fprintf(file, "\tif ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n"); 711 if (rt->rtNumRequestVar > 0) { 712 fprintf(file, "\t (msgh_size < "); 713 rtMinRequestSize(file, rt, "__Request"); 714 fprintf(file, ") || (msgh_size > (mach_msg_size_t)sizeof(__Request)))\n"); 715 } 716 else 717 fprintf(file, "\t (In0P->Head.msgh_size != (mach_msg_size_t)sizeof(__Request)))\n"); 718 } 719 else { 720 /* Expecting a complex message. */ 721 722 fprintf(file, "\tif ("); 723 if (rt->rtRetCArg != argNULL) 724 fprintf(file, "("); 725 fprintf(file, "!(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n"); 726 fprintf(file, "\t (In0P->msgh_body.msgh_descriptor_count != %d) ||\n", rt->rtRequestKPDs); 727 if (rt->rtNumRequestVar > 0) { 728 fprintf(file, "\t (msgh_size < "); 729 rtMinRequestSize(file, rt, "__Request"); 730 fprintf(file, ") || (msgh_size > (mach_msg_size_t)sizeof(__Request))"); 731 } 732 else 733 fprintf(file, "\t (In0P->Head.msgh_size != (mach_msg_size_t)sizeof(__Request))"); 734 if (rt->rtRetCArg == argNULL) 735 fprintf(file, ")\n"); 736 else { 737 fprintf(file, ") &&\n"); 738 fprintf(file, "\t ((In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n"); 739 fprintf(file, "\t In0P->Head.msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) ||\n"); 740 fprintf(file, "\t ((mig_reply_error_t *)In0P)->RetCode == KERN_SUCCESS))\n"); 741 } 742 } 743 fprintf(file, "\t\treturn MIG_BAD_ARGUMENTS;\n"); 744 fprintf(file, "#endif\t/* __MigTypeCheck */\n"); 745 fprintf(file, "\n"); 746} 747 748void 749WriteRequestNDRConvertIntRepArgCond(FILE *file, argument_t *arg) 750{ 751 routine_t *rt = arg->argRoutine; 752 753 fprintf(file, "defined(__NDR_convert__int_rep__Request__%s_t__%s__defined)", rt->rtName, arg->argMsgField); 754} 755 756void 757WriteRequestNDRConvertCharRepArgCond(FILE *file, argument_t *arg) 758{ 759 routine_t *rt = arg->argRoutine; 760 761 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut) 762 fprintf(file, "defined(__NDR_convert__char_rep__Request__%s_t__%s__defined)", rt->rtName, arg->argMsgField); 763 else 764 fprintf(file, "0"); 765} 766 767void 768WriteRequestNDRConvertFloatRepArgCond(FILE *file, argument_t *arg) 769{ 770 routine_t *rt = arg->argRoutine; 771 772 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut) 773 fprintf(file, "defined(__NDR_convert__float_rep__Request__%s_t__%s__defined)", rt->rtName, arg->argMsgField); 774 else 775 fprintf(file, "0"); 776} 777 778void 779WriteRequestNDRConvertIntRepArgDecl(FILE *file, argument_t *arg) 780{ 781 WriteNDRConvertArgDecl(file, arg, "int_rep", "Request"); 782} 783 784void 785WriteRequestNDRConvertCharRepArgDecl(FILE *file, argument_t *arg) 786{ 787 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut) 788 WriteNDRConvertArgDecl(file, arg, "char_rep", "Request"); 789} 790 791void 792WriteRequestNDRConvertFloatRepArgDecl(FILE *file, argument_t *arg) 793{ 794 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut) 795 WriteNDRConvertArgDecl(file, arg, "float_rep", "Request"); 796} 797 798void 799WriteRequestNDRConvertArgUse(FILE *file, argument_t *arg, char *convert) 800{ 801 routine_t *rt = arg->argRoutine; 802 argument_t *count = arg->argCount; 803 char argname[MAX_STR_LEN]; 804 805 if ((akIdent(arg->argKind) == akeCount || akIdent(arg->argKind) == akeCountInOut) && 806 (arg->argParent && akCheck(arg->argParent->argKind, akbSendNdr))) 807 return; 808 809 if (arg->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR) { 810 if (count && !arg->argSameCount && !strcmp(convert, "int_rep")) { 811 fprintf(file, "#if defined(__NDR_convert__int_rep__Request__%s_t__%s__defined)\n", rt->rtName, count->argMsgField); 812 fprintf(file, "\t\t__NDR_convert__int_rep__Request__%s_t__%s(&In%dP->%s, In%dP->NDR.int_rep);\n", rt->rtName, count->argMsgField, count->argRequestPos, count->argMsgField, count->argRequestPos); 813 fprintf(file, "#endif\t/* __NDR_convert__int_rep__Request__%s_t__%s__defined */\n", rt->rtName, count->argMsgField); 814 } 815 816 sprintf(argname, "(%s)(In%dP->%s.address)", FetchServerType(arg->argType), arg->argRequestPos, arg->argMsgField); 817 } 818 else { 819 sprintf(argname, "&In%dP->%s", arg->argRequestPos, arg->argMsgField); 820 } 821 822 fprintf(file, "#if defined(__NDR_convert__%s__Request__%s_t__%s__defined)\n", convert, rt->rtName, arg->argMsgField); 823 fprintf(file, "\t\t__NDR_convert__%s__Request__%s_t__%s(%s, In0P->NDR.%s", convert, rt->rtName, arg->argMsgField, argname, convert); 824 if (count) 825 fprintf(file, ", In%dP->%s", count->argRequestPos, count->argMsgField); 826 fprintf(file, ");\n"); 827 fprintf(file, "#endif\t/* __NDR_convert__%s__Request__%s_t__%s__defined */\n", convert, rt->rtName, arg->argMsgField); 828} 829 830void 831WriteRequestNDRConvertIntRepOneArgUse(FILE *file, argument_t *arg) 832{ 833 routine_t *rt = arg->argRoutine; 834 835 fprintf(file, "#if defined(__NDR_convert__int_rep__Request__%s_t__%s__defined)\n", rt->rtName, arg->argMsgField); 836 fprintf(file, "\tif (In0P->NDR.int_rep != NDR_record.int_rep)\n"); 837 fprintf(file, "\t\t__NDR_convert__int_rep__Request__%s_t__%s(&In%dP->%s, In%dP->NDR.int_rep);\n", rt->rtName, arg->argMsgField, arg->argRequestPos, arg->argMsgField, arg->argRequestPos); 838 fprintf(file, "#endif\t/* __NDR_convert__int_rep__Request__%s_t__%s__defined */\n", rt->rtName, arg->argMsgField); 839} 840 841void 842WriteRequestNDRConvertIntRepArgUse(FILE *file, argument_t *arg) 843{ 844 WriteRequestNDRConvertArgUse(file, arg, "int_rep"); 845} 846 847void 848WriteRequestNDRConvertCharRepArgUse(FILE *file, argument_t *arg) 849{ 850 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut) 851 WriteRequestNDRConvertArgUse(file, arg, "char_rep"); 852} 853 854void 855WriteRequestNDRConvertFloatRepArgUse(FILE *file, argument_t *arg) 856{ 857 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut) 858 WriteRequestNDRConvertArgUse(file, arg, "float_rep"); 859} 860 861static void 862WriteCalcArgSize(FILE *file, register argument_t *arg) 863{ 864 register ipc_type_t *ptype = arg->argType; 865 866 if (PackMsg == FALSE) { 867 fprintf(file, "%d", ptype->itTypeSize + ptype->itPadSize); 868 return; 869 } 870 871 if (IS_OPTIONAL_NATIVE(ptype)) 872 fprintf(file, "(In%dP->__Present__%s ? _WALIGNSZ_(%s) : 0)" , arg->argRequestPos, arg->argMsgField, ptype->itServerType); 873 else { 874 register ipc_type_t *btype = ptype->itElement; 875 argument_t *count = arg->argCount; 876 int multiplier = btype->itTypeSize; 877 878 if (btype->itTypeSize % itWordAlign != 0) 879 fprintf(file, "_WALIGN_"); 880 fprintf(file, "("); 881 882 if (multiplier > 1) 883 fprintf(file, "%d * ", multiplier); 884 fprintf(file, "In%dP->%s", count->argRequestPos, count->argMsgField); 885 fprintf(file, ")"); 886 } 887} 888 889static void 890WriteCheckArgSize(FILE *file, routine_t *rt, argument_t *arg, const char *comparator) 891{ 892 register ipc_type_t *ptype = arg->argType; 893 894 895 fprintf(file, "\tif (((msgh_size - "); 896 rtMinRequestSize(file, rt, "__Request"); 897 fprintf(file, ") "); 898 if (PackMsg == FALSE) { 899 fprintf(file, "%s %d)", comparator, ptype->itTypeSize + ptype->itPadSize); 900 } else if (IS_OPTIONAL_NATIVE(ptype)) { 901 fprintf(file, "%s (In%dP->__Present__%s ? _WALIGNSZ_(%s) : 0))" , comparator, arg->argRequestPos, arg->argMsgField, ptype->itServerType); 902 } else { 903 register ipc_type_t *btype = ptype->itElement; 904 argument_t *count = arg->argCount; 905 int multiplier = btype->itTypeSize; 906 907 if (multiplier > 1) 908 fprintf(file, "/ %d ", multiplier); 909 fprintf(file, "< In%dP->%s) ||\n", count->argRequestPos, count->argMsgField); 910 fprintf(file, "\t (msgh_size %s ", comparator); 911 rtMinRequestSize(file, rt, "__Request"); 912 fprintf(file, " + "); 913 WriteCalcArgSize(file, arg); 914 fprintf(file, ")"); 915 } 916 fprintf(file, ")\n\t\treturn MIG_BAD_ARGUMENTS;\n"); 917} 918 919static void 920WriteCheckMsgSize(FILE *file, register argument_t *arg) 921{ 922 register routine_t *rt = arg->argRoutine; 923 924 if (arg->argCount && !arg->argSameCount) 925 WriteRequestNDRConvertIntRepOneArgUse(file, arg->argCount); 926 if (arg->argRequestPos == rt->rtMaxRequestPos) { 927 fprintf(file, "#if\t__MigTypeCheck\n"); 928 929 /* verify that the user-code-provided count does not exceed the maximum count allowed by the type. */ 930 fprintf(file, "\t" "if ( In%dP->%s > %d )\n", arg->argCount->argRequestPos, arg->argCount->argMsgField, arg->argType->itNumber); 931 fputs("\t\t" "return MIG_BAD_ARGUMENTS;\n", file); 932 /* ...end... */ 933 934 WriteCheckArgSize(file, rt, arg, "!="); 935 936 fprintf(file, "#endif\t/* __MigTypeCheck */\n"); 937 } 938 else { 939 /* If there aren't any more variable-sized arguments after this, 940 then we must check for exact msg-size and we don't need to 941 update msgh_size. */ 942 943 boolean_t LastVarArg = arg->argRequestPos+1 == rt->rtNumRequestVar; 944 945 /* calculate the actual size in bytes of the data field. note 946 that this quantity must be a multiple of four. hence, if 947 the base type size isn't a multiple of four, we have to 948 round up. note also that btype->itNumber must 949 divide btype->itTypeSize (see itCalculateSizeInfo). */ 950 951 fprintf(file, "\tmsgh_size_delta = "); 952 WriteCalcArgSize(file, arg); 953 fprintf(file, ";\n"); 954 fprintf(file, "#if\t__MigTypeCheck\n"); 955 956 /* verify that the user-code-provided count does not exceed the maximum count allowed by the type. */ 957 fprintf(file, "\t" "if ( In%dP->%s > %d )\n", arg->argCount->argRequestPos, arg->argCount->argMsgField, arg->argType->itNumber); 958 fputs("\t\t" "return MIG_BAD_ARGUMENTS;\n", file); 959 /* ...end... */ 960 961 /* Don't decrement msgh_size until we've checked that 962 it won't underflow. */ 963 WriteCheckArgSize(file, rt, arg, LastVarArg ? "!=" : "<"); 964 965 if (!LastVarArg) 966 fprintf(file, "\tmsgh_size -= msgh_size_delta;\n"); 967 968 fprintf(file, "#endif\t/* __MigTypeCheck */\n"); 969 } 970 fprintf(file, "\n"); 971} 972 973static char * 974InArgMsgField(register argument_t *arg, char *str) 975{ 976 static char buffer[MAX_STR_LEN]; 977 char who[20] = {0}; 978 979 /* 980 * Inside the kernel, the request and reply port fields 981 * really hold ipc_port_t values, not mach_port_t values. 982 * Hence we must cast the values. 983 */ 984 985 if (!(arg->argFlags & flRetCode)) { 986 if (akCheck(arg->argKind, akbServerImplicit)) 987 sprintf(who, "TrailerP->"); 988 else 989 sprintf(who, "In%dP->", arg->argRequestPos); 990 } 991 992#ifdef MIG_KERNEL_PORT_CONVERSION 993 if (IsKernelServer && 994 ((akIdent(arg->argKind) == akeRequestPort) || 995 (akIdent(arg->argKind) == akeReplyPort))) 996 sprintf(buffer, "(ipc_port_t) %s%s%s", who, str, (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField); 997 else 998#endif 999 sprintf(buffer, "%s%s%s", who, str, (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField); 1000 1001 return buffer; 1002} 1003 1004static void 1005WriteExtractArgValue(FILE *file, register argument_t *arg) 1006{ 1007 register ipc_type_t *it = arg->argType; 1008 string_t recast; 1009 1010#ifdef MIG_KERNEL_PORT_CONVERSION 1011 if (IsKernelServer && it->itPortType && streql(it->itServerType, "ipc_port_t") 1012 && akIdent(arg->argKind) != akeRequestPort 1013 && akIdent(arg->argKind) != akeReplyPort) 1014 recast = "(mach_port_t)"; 1015 else 1016#endif 1017 recast = ""; 1018 if (it->itInTrans != strNULL) 1019 WriteCopyType(file, it, "%s", "/* %s */ %s(%s%s)", arg->argVarName, it->itInTrans, recast, InArgMsgField(arg, "")); 1020 else 1021 WriteCopyType(file, it, "%s", "/* %s */ %s%s", arg->argVarName, recast, InArgMsgField(arg, "")); 1022 1023 fprintf(file, "\n"); 1024} 1025 1026/* 1027 * argKPD_Extract discipline for Port types. 1028 */ 1029static void 1030WriteExtractKPD_port(FILE *file, register argument_t *arg) 1031{ 1032 register ipc_type_t *it = arg->argType; 1033 char *recast = ""; 1034 1035 WriteKPD_Iterator(file, TRUE, it->itVarArray, arg, FALSE); 1036 /* translation function do not apply to complex types */ 1037#ifdef MIG_KERNEL_PORT_CONVERSION 1038 if (IsKernelServer) 1039 recast = "(mach_port_t)"; 1040#endif 1041 fprintf(file, "\t\t%s[i] = %sptr->name;\n", arg->argVarName, recast); 1042 fprintf(file, "\t}\n"); 1043} 1044 1045/* 1046 * argKPD_Extract discipline for out-of-line types. 1047 */ 1048static void 1049WriteExtractKPD_ool(FILE *file, register argument_t *arg) 1050{ 1051 register ipc_type_t *it = arg->argType; 1052 1053 WriteKPD_Iterator(file, TRUE, it->itVarArray, arg, FALSE); 1054 fprintf(file, "\t\t%s[i] = ptr->address;\n", arg->argVarName); 1055 fprintf(file, "\t}\n"); 1056} 1057 1058/* 1059 * argKPD_Extract discipline for out-of-line Port types. 1060 */ 1061static void 1062WriteExtractKPD_oolport(FILE *file, register argument_t *arg) 1063{ 1064 register ipc_type_t *it = arg->argType; 1065 1066 WriteKPD_Iterator(file, TRUE, it->itVarArray, arg, FALSE); 1067 fprintf(file, "\t\t%s[i] = ptr->address;\n", arg->argVarName); 1068 fprintf(file, "\t}\n"); 1069 if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbSendRcv)) { 1070 register argument_t *poly = arg->argPoly; 1071 register char *pref = poly->argByReferenceServer ? "*" : ""; 1072 1073 fprintf(file, "\t%s%s = In%dP->%s[0].disposition;\n", pref, poly->argVarName, arg->argRequestPos, arg->argMsgField); 1074 } 1075} 1076 1077 1078static void 1079WriteInitializeCount(FILE *file, register argument_t *arg) 1080{ 1081 register ipc_type_t *ptype = arg->argParent->argType; 1082 register ipc_type_t *btype = ptype->itElement; 1083 identifier_t newstr; 1084 1085 /* 1086 * Initialize 'count' argument for variable-length inline OUT parameter 1087 * with maximum allowed number of elements. 1088 */ 1089 1090 if (akCheck(arg->argKind, akbVarNeeded)) 1091 newstr = arg->argMsgField; 1092 else 1093 newstr = (identifier_t)strconcat("OutP->", arg->argMsgField); 1094 1095 fprintf(file, "\t%s = ", newstr); 1096 if (IS_MULTIPLE_KPD(ptype)) 1097 fprintf(file, "%d;\n", ptype->itKPD_Number); 1098 else 1099 fprintf(file, "%d;\n", btype->itNumber? ptype->itNumber/btype->itNumber : 0); 1100 1101 /* 1102 * If the user passed in a count, then we use the minimum. 1103 * We can't let the user completely override our maximum, 1104 * or the user might convince the server to overwrite the buffer. 1105 */ 1106 1107 if (arg->argCInOut != argNULL) { 1108 char *msgfield = InArgMsgField(arg->argCInOut, ""); 1109 1110 fprintf(file, "\tif (%s < %s)\n", msgfield, newstr); 1111 fprintf(file, "\t\t%s = %s;\n", newstr, msgfield); 1112 } 1113 1114 fprintf(file, "\n"); 1115} 1116 1117static void 1118WriteAdjustRequestMsgPtr(FILE *file, register argument_t *arg) 1119{ 1120 register ipc_type_t *ptype = arg->argType; 1121 1122 if (PackMsg == FALSE) { 1123 fprintf(file, "\t*In%dPP = In%dP = (__Request *) ((pointer_t) In%dP);\n\n", arg->argRequestPos+1, arg->argRequestPos+1, arg->argRequestPos); 1124 return; 1125 } 1126 1127 fprintf(file, "\t*In%dPP = In%dP = (__Request *) ((pointer_t) In%dP + msgh_size_delta - ", arg->argRequestPos+1, arg->argRequestPos+1, arg->argRequestPos); 1128 if (IS_OPTIONAL_NATIVE(ptype)) 1129 fprintf(file, "_WALIGNSZ_(%s)", ptype->itUserType); 1130 else 1131 fprintf(file, "%d", ptype->itTypeSize + ptype->itPadSize); 1132 fprintf(file, ");\n\n"); 1133} 1134 1135static void 1136WriteCheckRequestTrailerArgs(FILE *file, routine_t *rt) 1137{ 1138 register argument_t *arg; 1139 1140 if (rt->rtServerImpl) 1141 WriteCheckTrailerHead(file, rt, FALSE); 1142 1143 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { 1144 if (akCheck(arg->argKind, akbServerImplicit)) 1145 WriteCheckTrailerSize(file, FALSE, arg); 1146 } 1147} 1148 1149static void 1150WriteExtractArg(FILE *file, register argument_t *arg) 1151{ 1152 if (akCheckAll(arg->argKind, akbSendRcv|akbVarNeeded)) { 1153 if (akCheck(arg->argKind, akbSendKPD)) 1154 (*arg->argKPD_Extract)(file, arg); 1155 else 1156 WriteExtractArgValue(file, arg); 1157 } 1158 1159 if ((akIdent(arg->argKind) == akeCount) && 1160 akCheck(arg->argKind, akbReturnSnd)) { 1161 1162 register ipc_type_t *ptype = arg->argParent->argType; 1163 /* 1164 * the count will be initialized to 0 in the case of 1165 * unbounded arrays (MigInLine = TRUE): this is because 1166 * the old interface used to pass to the target procedure 1167 * the maximum in-line size (it was 2048 bytes) 1168 */ 1169 if (IS_VARIABLE_SIZED_UNTYPED(ptype) || 1170 IS_MIG_INLINE_EMUL(ptype) || 1171 (IS_MULTIPLE_KPD(ptype) && ptype->itVarArray)) 1172 WriteInitializeCount(file, arg); 1173 } 1174} 1175 1176static void 1177WriteServerCallArg(FILE *file, register argument_t *arg) 1178{ 1179 ipc_type_t *it = arg->argType; 1180 boolean_t NeedClose = FALSE; 1181 string_t at = (arg->argByReferenceServer || 1182 it->itNativePointer) ? "&" : ""; 1183 string_t star = (arg->argByReferenceServer) ? " *" : ""; 1184 string_t msgfield = 1185 (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField; 1186 1187 if ((it->itInTrans != strNULL) && 1188 akCheck(arg->argKind, akbSendRcv) && 1189 !akCheck(arg->argKind, akbVarNeeded)) { 1190 fprintf(file, "%s%s(", at, it->itInTrans); 1191 NeedClose = TRUE; 1192 } 1193 1194 if (akCheckAll(arg->argKind, akbVarNeeded|akbServerArg)) 1195 fprintf(file, "%s%s", at, arg->argVarName); 1196 else if (akCheckAll(arg->argKind, akbSendRcv|akbSendKPD)) { 1197 if (!it->itInLine) 1198 /* recast the void *, although it is not necessary */ 1199 fprintf(file, "(%s%s)%s(%s)", it->itTransType, star, at, InArgMsgField(arg, "")); 1200 else 1201#ifdef MIG_KERNEL_PORT_CONVERSION 1202 if (IsKernelServer && streql(it->itServerType, "ipc_port_t")) 1203 /* recast the port to the kernel internal form value */ 1204 fprintf(file, "(ipc_port_t%s)%s(%s)", star, at, InArgMsgField(arg, "")); 1205 else 1206#endif 1207 fprintf(file, "%s%s", at, InArgMsgField(arg, "")); 1208 } 1209 else if (akCheck(arg->argKind, akbSendRcv)) { 1210 if (IS_OPTIONAL_NATIVE(it)) { 1211 fprintf(file, "(%s ? ", InArgMsgField(arg, "__Present__")); 1212 fprintf(file, "%s%s.__Real__%s : %s)", at, InArgMsgField(arg, ""), arg->argMsgField, it->itBadValue); 1213 } 1214 else 1215 fprintf(file, "%s%s", at, InArgMsgField(arg, "")); 1216 } 1217 else if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnKPD)) { 1218 if (!it->itInLine) 1219 /* recast the void *, although it is not necessary */ 1220 fprintf(file, "(%s%s)%s(OutP->%s)", it->itTransType, star, at, msgfield); 1221 else 1222#ifdef MIG_KERNEL_PORT_CONVERSION 1223 if (IsKernelServer && streql(it->itServerType, "ipc_port_t")) 1224 /* recast the port to the kernel internal form value */ 1225 fprintf(file, "(mach_port_t%s)%s(OutP->%s)", star, at, msgfield); 1226 else 1227#endif 1228 fprintf(file, "%sOutP->%s", at, msgfield); 1229 1230 } 1231 else if (akCheck(arg->argKind, akbReturnSnd)) 1232 fprintf(file, "%sOutP->%s", at, msgfield); 1233 1234 if (NeedClose) 1235 fprintf(file, ")"); 1236} 1237 1238/* 1239 * Shrunk version of WriteServerCallArg, to implement the RetCode functionality: 1240 * we have received a mig_reply_error_t, therefore we want to call the target 1241 * routine with all 0s except for the error code (and the implicit data). 1242 * We know that we are a SimpleRoutine. 1243 */ 1244static void 1245WriteConditionalCallArg(FILE *file, register argument_t *arg) 1246{ 1247 ipc_type_t *it = arg->argType; 1248 boolean_t NeedClose = FALSE; 1249 1250 if ((it->itInTrans != strNULL) && 1251 akCheck(arg->argKind, akbSendRcv) && 1252 !akCheck(arg->argKind, akbVarNeeded)) { 1253 fprintf(file, "%s(", it->itInTrans); 1254 NeedClose = TRUE; 1255 } 1256 1257 if (akCheck(arg->argKind, akbSendRcv)) { 1258 if (akIdent(arg->argKind) == akeRequestPort || 1259 akCheck(arg->argKind, akbServerImplicit)) 1260 fprintf(file, "%s", InArgMsgField(arg, "")); 1261 else if (akIdent(arg->argKind) == akeRetCode) 1262 fprintf(file, "((mig_reply_error_t *)In0P)->RetCode"); 1263 else 1264 fprintf(file, "(%s)(0)", it->itTransType); 1265 } 1266 1267 if (NeedClose) 1268 fprintf(file, ")"); 1269} 1270 1271static void 1272WriteDestroyArg(FILE *file, register argument_t *arg) 1273{ 1274 register ipc_type_t *it = arg->argType; 1275 1276 /* 1277 * Deallocate IN/INOUT out-of-line args if specified by "auto" flag. 1278 * 1279 * We also have to deallocate in the cases where the target routine 1280 * is given a itInLine semantic whereas the underlying transmission 1281 * was out-of-line 1282 */ 1283 if ((argIsIn(arg) && akCheck(arg->argKind, akbSendKPD|akbReturnKPD) && 1284 arg->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR && 1285 (arg->argFlags & flAuto)) 1286 || 1287 IS_MIG_INLINE_EMUL(it) 1288 ) { 1289 /* 1290 * Deallocate only if out-of-line. 1291 */ 1292 argument_t *count = arg->argCount; 1293 ipc_type_t *btype = it->itElement; 1294 int multiplier = btype->itNumber ? btype->itSize / (8 * btype->itNumber) : 0; 1295 1296 if (IsKernelServer) { 1297 fprintf(file, "#if __MigKernelSpecificCode\n"); 1298 fprintf(file, "\tvm_map_copy_discard(%s);\n", InArgMsgField(arg, "")); 1299 fprintf(file, "#else\n"); 1300 } 1301 fprintf(file, "\tmig_deallocate((vm_offset_t) %s, ", InArgMsgField(arg, "")); 1302 if (it->itVarArray) { 1303 if (multiplier > 1) 1304 fprintf(file, "%d * ", multiplier); 1305 fprintf(file, "%s);\n", InArgMsgField(count, "")); 1306 } 1307 else 1308 fprintf(file, "%d);\n", (it->itNumber * it->itSize + 7) / 8); 1309 if (IsKernelServer) { 1310 fprintf(file, "#endif /* __MigKernelSpecificCode */\n"); 1311 } 1312 fprintf(file, "\t%s = (void *) 0;\n", InArgMsgField(arg, "")); 1313 fprintf(file, "\tIn%dP->%s.%s = (mach_msg_size_t) 0;\n", arg->argRequestPos, arg->argMsgField, (RPCPortArray(arg) ? "count" : "size")); 1314 } 1315 else { 1316 if (akCheck(arg->argKind, akbVarNeeded)) 1317 fprintf(file, "\t%s(%s);\n", it->itDestructor, arg->argVarName); 1318 else 1319 fprintf(file, "\t%s(%s);\n", it->itDestructor, InArgMsgField(arg, "")); 1320 } 1321} 1322 1323static void 1324WriteDestroyPortArg(FILE *file, register argument_t *arg) 1325{ 1326 register ipc_type_t *it = arg->argType; 1327 1328 /* 1329 * If a translated port argument occurs in the body of a request 1330 * message, and the message is successfully processed, then the 1331 * port right should be deallocated. However, the called function 1332 * didn't see the port right; it saw the translation. So we have 1333 * to release the port right for it. 1334 * 1335 * The test over it->itInTrans will exclude any complex type 1336 * made out of ports 1337 */ 1338 if ((it->itInTrans != strNULL) && 1339 (it->itOutName == MACH_MSG_TYPE_PORT_SEND)) { 1340 fprintf(file, "\n"); 1341 fprintf(file, "\tif (IP_VALID((ipc_port_t)%s))\n", InArgMsgField(arg, "")); 1342 fprintf(file, "\t\tipc_port_release_send((ipc_port_t)%s);\n", InArgMsgField(arg, "")); 1343 } 1344} 1345 1346/* 1347 * Check whether WriteDestroyPortArg would generate any code for arg. 1348 */ 1349boolean_t 1350CheckDestroyPortArg(register argument_t *arg) 1351{ 1352 register ipc_type_t *it = arg->argType; 1353 1354 if ((it->itInTrans != strNULL) && 1355 (it->itOutName == MACH_MSG_TYPE_PORT_SEND)) { 1356 return TRUE; 1357 } 1358 return FALSE; 1359} 1360 1361static void 1362WriteServerCall(FILE *file, routine_t *rt, void (*func)()) 1363{ 1364 argument_t *arg = rt->rtRetCode; 1365 ipc_type_t *it = arg->argType; 1366 boolean_t NeedClose = FALSE; 1367 1368 fprintf(file, "\t"); 1369 if (akCheck(arg->argKind, akbVarNeeded)) 1370 fprintf(file, "%s = ", arg->argMsgField); 1371 else 1372 fprintf(file, "OutP->%s = ", arg->argMsgField); 1373 if (it->itOutTrans != strNULL) { 1374 fprintf(file, "%s(", it->itOutTrans); 1375 NeedClose = TRUE; 1376 } 1377 fprintf(file, "%s(", rt->rtServerName); 1378 WriteList(file, rt->rtArgs, func, akbServerArg, ", ", ""); 1379 if (NeedClose) 1380 fprintf(file, ")"); 1381 fprintf(file, ");\n"); 1382} 1383 1384static void 1385WriteCheckReturnValue(FILE *file, register routine_t *rt) 1386{ 1387 argument_t *arg = rt->rtRetCode; 1388 char string[MAX_STR_LEN]; 1389 1390 if (akCheck(arg->argKind, akbVarNeeded)) 1391 sprintf(string, "%s", arg->argMsgField); 1392 else 1393 sprintf(string, "OutP->%s", arg->argMsgField); 1394 fprintf(file, "\tif (%s != KERN_SUCCESS) {\n", string); 1395 fprintf(file, "\t\tMIG_RETURN_ERROR(OutP, %s);\n", string); 1396 fprintf(file, "\t}\n"); 1397} 1398 1399/* 1400 * WriteInitKPD_port, WriteInitKPD_ool, WriteInitKPD_oolport 1401 * initializes the OutP KPD fields (this job cannot be done once 1402 * the target routine has been called, otherwise informations 1403 * would be lost) 1404 */ 1405/* 1406 * argKPD_Init discipline for Port types. 1407 */ 1408static void 1409WriteInitKPD_port(FILE *file, register argument_t *arg) 1410{ 1411 register ipc_type_t *it = arg->argType; 1412 char *subindex = ""; 1413 boolean_t close = FALSE; 1414 char firststring[MAX_STR_LEN]; 1415 char string[MAX_STR_LEN]; 1416 1417 if (IS_MULTIPLE_KPD(it)) { 1418 WriteKPD_Iterator(file, FALSE, FALSE, arg, TRUE); 1419 (void)sprintf(firststring, "\t*ptr"); 1420 (void)sprintf(string, "\tptr->"); 1421 subindex = "[i]"; 1422 close = TRUE; 1423 } 1424 else { 1425 (void)sprintf(firststring, "OutP->%s", arg->argMsgField); 1426 (void)sprintf(string, "OutP->%s.", arg->argMsgField); 1427 } 1428 1429 fprintf(file, "#if\tUseStaticTemplates\n"); 1430 fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName); 1431 fprintf(file, "#else\t/* UseStaticTemplates */\n"); 1432 if (IS_MULTIPLE_KPD(it) && it->itVarArray) 1433 fprintf(file, "\t%sname = MACH_PORT_NULL;\n", string); 1434 if (arg->argPoly == argNULL) { 1435 if (IsKernelServer) { 1436 fprintf(file, "#if __MigKernelSpecificCode\n"); 1437 fprintf(file, "\t%sdisposition = %s;\n", string, it->itOutNameStr); 1438 fprintf(file, "#else\n"); 1439 } 1440 fprintf(file, "\t%sdisposition = %s;\n", string, it->itInNameStr); 1441 if (IsKernelServer) 1442 fprintf(file, "#endif /* __MigKernelSpecificCode */\n"); 1443 } 1444 fprintf(file, "\t%stype = MACH_MSG_PORT_DESCRIPTOR;\n", string); 1445 fprintf(file, "#endif\t/* UseStaticTemplates */\n"); 1446 if (close) 1447 fprintf(file, "\t }\n\t}\n"); 1448 fprintf(file, "\n"); 1449} 1450 1451/* 1452 * argKPD_Init discipline for out-of-line types. 1453 */ 1454static void 1455WriteInitKPD_ool(FILE *file, register argument_t *arg) 1456{ 1457 register ipc_type_t *it = arg->argType; 1458 char firststring[MAX_STR_LEN]; 1459 char string[MAX_STR_LEN]; 1460 boolean_t VarArray; 1461 u_int howmany, howbig; 1462 1463 if (IS_MULTIPLE_KPD(it)) { 1464 WriteKPD_Iterator(file, FALSE, FALSE, arg, TRUE); 1465 (void)sprintf(firststring, "\t*ptr"); 1466 (void)sprintf(string, "\tptr->"); 1467 VarArray = it->itElement->itVarArray; 1468 howmany = it->itElement->itNumber; 1469 howbig = it->itElement->itSize; 1470 } 1471 else { 1472 (void)sprintf(firststring, "OutP->%s", arg->argMsgField); 1473 (void)sprintf(string, "OutP->%s.", arg->argMsgField); 1474 VarArray = it->itVarArray; 1475 howmany = it->itNumber; 1476 howbig = it->itSize; 1477 } 1478 1479 fprintf(file, "#if\tUseStaticTemplates\n"); 1480 fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName); 1481 fprintf(file, "#else\t/* UseStaticTemplates */\n"); 1482 if (!VarArray) 1483 fprintf(file, "\t%ssize = %d;\n", string, (howmany * howbig + 7)/8); 1484 if (arg->argDeallocate != d_MAYBE) 1485 fprintf(file, "\t%sdeallocate = %s;\n", string, (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE"); 1486 fprintf(file, "\t%scopy = %s;\n", string, (arg->argFlags & flPhysicalCopy) ? "MACH_MSG_PHYSICAL_COPY" : "MACH_MSG_VIRTUAL_COPY"); 1487#ifdef ALIGNMENT 1488 fprintf(file, "\t%salignment = MACH_MSG_ALIGN_%d;\n", string, arg->argMsgField, (howbig < 8) ? 1 : howbig / 8); 1489#endif 1490 fprintf(file, "\t%stype = MACH_MSG_OOL_DESCRIPTOR;\n", string); 1491 fprintf(file, "#endif\t/* UseStaticTemplates */\n"); 1492 1493 if (IS_MULTIPLE_KPD(it)) 1494 fprintf(file, "\t }\n\t}\n"); 1495 fprintf(file, "\n"); 1496} 1497 1498/* 1499 * argKPD_Init discipline for out-of-line Port types. 1500 */ 1501static void 1502WriteInitKPD_oolport(FILE *file, register argument_t *arg) 1503{ 1504 register ipc_type_t *it = arg->argType; 1505 boolean_t VarArray; 1506 ipc_type_t *howit; 1507 u_int howmany; 1508 char firststring[MAX_STR_LEN]; 1509 char string[MAX_STR_LEN]; 1510 1511 if (IS_MULTIPLE_KPD(it)) { 1512 WriteKPD_Iterator(file, FALSE, FALSE, arg, TRUE); 1513 (void)sprintf(firststring, "\t*ptr"); 1514 (void)sprintf(string, "\tptr->"); 1515 VarArray = it->itElement->itVarArray; 1516 howmany = it->itElement->itNumber; 1517 howit = it->itElement; 1518 } 1519 else { 1520 (void)sprintf(firststring, "OutP->%s", arg->argMsgField); 1521 (void)sprintf(string, "OutP->%s.", arg->argMsgField); 1522 VarArray = it->itVarArray; 1523 howmany = it->itNumber; 1524 howit = it; 1525 } 1526 1527 fprintf(file, "#if\tUseStaticTemplates\n"); 1528 fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName); 1529 fprintf(file, "#else\t/* UseStaticTemplates */\n"); 1530 1531 if (!VarArray) 1532 fprintf(file, "\t%scount = %d;\n", string, howmany); 1533 if (arg->argPoly == argNULL) { 1534 if (IsKernelServer) { 1535 fprintf(file, "#if\t__MigKernelSpecificCode\n"); 1536 fprintf(file, "\t%sdisposition = %s;\n", string, howit->itOutNameStr); 1537 fprintf(file, "#else\n"); 1538 } 1539 fprintf(file, "\t%sdisposition = %s;\n", string, howit->itInNameStr); 1540 if (IsKernelServer) 1541 fprintf(file, "#endif /* __MigKernelSpecificCode */\n"); 1542 } 1543 if (arg->argDeallocate != d_MAYBE) 1544 fprintf(file, "\t%sdeallocate = %s;\n", string, (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE"); 1545 fprintf(file, "\t%stype = MACH_MSG_OOL_PORTS_DESCRIPTOR;\n", string); 1546 fprintf(file, "#endif\t/* UseStaticTemplates */\n"); 1547 1548 if (IS_MULTIPLE_KPD(it)) 1549 fprintf(file, "\t }\n\t}\n"); 1550 fprintf(file, "\n"); 1551} 1552 1553static void 1554WriteInitKPDValue(FILE *file, register argument_t *arg) 1555{ 1556 (*arg->argKPD_Init)(file, arg); 1557} 1558 1559static void 1560WriteAdjustMsgCircular(FILE *file, register argument_t *arg) 1561{ 1562 fprintf(file, "\n"); 1563 1564 fprintf(file,"#if\t__MigKernelSpecificCode\n"); 1565 if (arg->argType->itOutName == MACH_MSG_TYPE_POLYMORPHIC) 1566 fprintf(file, "\tif (%s == MACH_MSG_TYPE_PORT_RECEIVE)\n", arg->argPoly->argVarName); 1567 1568 /* 1569 * The carried port right can be accessed in OutP->XXXX. Normally 1570 * the server function stuffs it directly there. If it is InOut, 1571 * then it has already been copied into the reply message. 1572 * If the server function deposited it into a variable (perhaps 1573 * because the reply message is variable-sized) then it has already 1574 * been copied into the reply message. 1575 * 1576 * The old MiG does not check for circularity in the case of 1577 * array of ports. So do I ... 1578 */ 1579 1580 fprintf(file, "\t if (IP_VALID((ipc_port_t) In0P->Head.msgh_reply_port) &&\n"); 1581 fprintf(file, "\t IP_VALID((ipc_port_t) OutP->%s.name) &&\n", arg->argMsgField); 1582 fprintf(file, "\t ipc_port_check_circularity((ipc_port_t) OutP->%s.name, (ipc_port_t) In0P->Head.msgh_reply_port))\n", arg->argMsgField); 1583 fprintf(file, "\t\tOutP->Head.msgh_bits |= MACH_MSGH_BITS_CIRCULAR;\n"); 1584 fprintf(file, "#endif /* __MigKernelSpecificCode */\n"); 1585} 1586 1587/* 1588 * argKPD_Pack discipline for Port types. 1589 */ 1590static void 1591WriteKPD_port(FILE *file, register argument_t *arg) 1592{ 1593 register ipc_type_t *it = arg->argType; 1594 char *subindex = ""; 1595 char *recast = ""; 1596 boolean_t close = FALSE; 1597 char string[MAX_STR_LEN]; 1598 ipc_type_t *real_it; 1599 1600 if (akCheck(arg->argKind, akbVarNeeded)) { 1601 if (IS_MULTIPLE_KPD(it)) { 1602 WriteKPD_Iterator(file, FALSE, it->itVarArray, arg, TRUE); 1603 (void)sprintf(string, "\tptr->"); 1604 subindex = "[i]"; 1605 close = TRUE; 1606 real_it = it->itElement; 1607 } 1608 else { 1609 (void)sprintf(string, "OutP->%s.", arg->argMsgField); 1610 real_it = it; 1611 } 1612#ifdef MIG_KERNEL_PORT_CONVERSIONS 1613 if (IsKernelServer && streql(real_it->itTransType, "ipc_port_t")) 1614 recast = "(mach_port_t)"; 1615#endif 1616 1617 if (it->itOutTrans != strNULL && !close) 1618 fprintf(file, "\t%sname = (mach_port_t)%s(%s);\n", string, it->itOutTrans, arg->argVarName); 1619 else 1620 fprintf(file, "\t%sname = %s%s%s;\n", string, recast, arg->argVarName, subindex); 1621 if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbReturnSnd)) { 1622 register argument_t *poly = arg->argPoly; 1623 1624 if (akCheck(arg->argPoly->argKind, akbVarNeeded)) 1625 fprintf(file, "\t%sdisposition = %s;\n", string, poly->argVarName); 1626 else if (close) 1627 fprintf(file, "\t%sdisposition = OutP->%s;\n", string, poly->argSuffix); 1628 } 1629 if (close) 1630 fprintf(file, "\t }\n\t}\n"); 1631 fprintf(file, "\n"); 1632 } 1633 else if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbReturnSnd|akbVarNeeded)) 1634 fprintf(file, "\tOutP->%s.disposition = %s;\n", arg->argMsgField, arg->argPoly->argVarName); 1635 /* 1636 * If this is a KernelServer, and the reply message contains 1637 * a receive right, we must check for the possibility of a 1638 * port/message circularity. If queueing the reply message 1639 * would cause a circularity, we mark the reply message 1640 * with the circular bit. 1641 */ 1642 if (IsKernelServer && !(IS_MULTIPLE_KPD(it)) && 1643 ((arg->argType->itOutName == MACH_MSG_TYPE_PORT_RECEIVE) || 1644 (arg->argType->itOutName == MACH_MSG_TYPE_POLYMORPHIC))) 1645 WriteAdjustMsgCircular(file, arg); 1646} 1647 1648/* 1649 * argKPD_Pack discipline for out-of-line types. 1650 */ 1651static void 1652WriteKPD_ool(FILE *file, register argument_t *arg) 1653{ 1654 register ipc_type_t *it = arg->argType; 1655 char string[MAX_STR_LEN]; 1656 boolean_t VarArray; 1657 argument_t *count; 1658 u_int howbig; 1659 char *subindex; 1660 1661 if (IS_MULTIPLE_KPD(it)) { 1662 WriteKPD_Iterator(file, FALSE, it->itVarArray, arg, TRUE); 1663 (void)sprintf(string, "\tptr->"); 1664 VarArray = it->itElement->itVarArray; 1665 count = arg->argSubCount; 1666 howbig = it->itElement->itSize; 1667 subindex = "[i]"; 1668 } 1669 else { 1670 (void)sprintf(string, "OutP->%s.", arg->argMsgField); 1671 VarArray = it->itVarArray; 1672 count = arg->argCount; 1673 howbig = it->itSize; 1674 subindex = ""; 1675 } 1676 1677 if (akCheck(arg->argKind, akbVarNeeded)) 1678 fprintf(file, "\t%saddress = (void *)%s%s;\n", string, arg->argMsgField, subindex); 1679 if (arg->argDealloc != argNULL) 1680 if (akCheck(arg->argDealloc->argKind, akbVarNeeded) || IS_MULTIPLE_KPD(it)) 1681 fprintf(file, "\t%sdeallocate = %s;\n", string, arg->argDealloc->argVarName); 1682 if (VarArray) { 1683 fprintf(file, "\t%ssize = ", string); 1684 if (akCheck(count->argKind, akbVarNeeded)) 1685 fprintf(file, "%s%s", count->argName, subindex); 1686 else 1687 fprintf(file, "OutP->%s%s", count->argMsgField, subindex); 1688 1689 if (count->argMultiplier > 1 || howbig > 8) 1690 fprintf(file, " * %d;\n", count->argMultiplier * howbig / 8); 1691 else 1692 fprintf(file, ";\n"); 1693 } 1694 1695 if (IS_MULTIPLE_KPD(it)) { 1696 fprintf(file, "\t }\n"); 1697 if (it->itVarArray && !it->itElement->itVarArray) { 1698 fprintf(file, "\t for (i = j; i < %d; ptr++, i++)\n", it->itKPD_Number); 1699 /* since subordinate arrays aren't variable, they are initialized from template: 1700 here we must no-op 'em */ 1701 fprintf(file, "\t\tptr->size = 0;\n"); 1702 } 1703 fprintf(file, "\t}\n"); 1704 } 1705 fprintf(file, "\n"); 1706} 1707 1708/* 1709 * argKPD_Pack discipline for out-of-line Port types. 1710 */ 1711static void 1712WriteKPD_oolport(FILE *file, register argument_t *arg) 1713{ 1714 register ipc_type_t *it = arg->argType; 1715 boolean_t VarArray; 1716 argument_t *count; 1717 char *subindex, string[MAX_STR_LEN]; 1718 1719 if (IS_MULTIPLE_KPD(it)) { 1720 WriteKPD_Iterator(file, FALSE, it->itVarArray, arg, TRUE); 1721 (void)sprintf(string, "\tptr->"); 1722 VarArray = it->itElement->itVarArray; 1723 count = arg->argSubCount; 1724 subindex = "[i]"; 1725 } 1726 else { 1727 (void)sprintf(string, "OutP->%s.", arg->argMsgField); 1728 VarArray = it->itVarArray; 1729 count = arg->argCount; 1730 subindex = ""; 1731 } 1732 1733 if (akCheck(arg->argKind, akbVarNeeded)) 1734 fprintf(file, "\t%saddress = (void *)%s%s;\n", string, arg->argMsgField, subindex); 1735 if (arg->argDealloc != argNULL) 1736 if (akCheck(arg->argDealloc->argKind, akbVarNeeded) || IS_MULTIPLE_KPD(it)) 1737 fprintf(file, "\t%sdeallocate = %s;\n", string, arg->argDealloc->argVarName); 1738 if (VarArray) { 1739 fprintf(file, "\t%scount = ", string); 1740 if (akCheck(count->argKind, akbVarNeeded)) 1741 fprintf(file, "%s%s;\n", count->argName, subindex); 1742 else 1743 fprintf(file, "OutP->%s%s;\n", count->argMsgField, subindex); 1744 } 1745 if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbReturnSnd)) 1746 if (akCheck(arg->argPoly->argKind, akbVarNeeded) || IS_MULTIPLE_KPD(it)) 1747 fprintf(file, "\t%sdisposition = %s;\n", string, arg->argPoly->argVarName); 1748 if (IS_MULTIPLE_KPD(it)) { 1749 fprintf(file, "\t }\n"); 1750 if (it->itVarArray && !it->itElement->itVarArray) { 1751 fprintf(file, "\t for (i = j; i < %d; ptr++, i++)\n", it->itKPD_Number); 1752 /* since subordinate arrays aren't variable, they are initialized from template: 1753 here we must no-op 'em */ 1754 fprintf(file, "\t%scount = 0;\n", string); 1755 } 1756 fprintf(file, "\t}\n"); 1757 } 1758 fprintf(file, "\n"); 1759} 1760 1761/* 1762 * argKPD_TypeCheck discipline for Port types. 1763 */ 1764static void 1765WriteTCheckKPD_port(FILE *file, register argument_t *arg) 1766{ 1767 register ipc_type_t *it = arg->argType; 1768 char *tab = ""; 1769 char string[MAX_STR_LEN]; 1770 boolean_t close = FALSE; 1771 1772 if (IS_MULTIPLE_KPD(it)) { 1773 WriteKPD_Iterator(file, TRUE, FALSE, arg, TRUE); 1774 (void)sprintf(string, "ptr->"); 1775 tab = "\t"; 1776 close = TRUE; 1777 } 1778 else 1779 (void)sprintf(string, "In%dP->%s.", arg->argRequestPos, arg->argMsgField); 1780 1781 fprintf(file, "\t%sif (%stype != MACH_MSG_PORT_DESCRIPTOR", tab, string); 1782 /* 1783 * We can't check disposition on varArray 1784 * (because some of the entries could be empty). 1785 */ 1786 if (!it->itVarArray) { 1787 if (arg->argPoly != argNULL) { 1788 switch (it->itOutName) { 1789 1790 case MACH_MSG_TYPE_MOVE_RECEIVE: 1791 fprintf(file, " || \n\t%s %sdisposition != MACH_MSG_TYPE_MOVE_RECEIVE", tab, string); 1792 break; 1793 1794 case MACH_MSG_TYPE_MOVE_SEND_ONCE: 1795 fprintf(file, " || (\n\t%s %sdisposition != MACH_MSG_TYPE_MOVE_SEND_ONCE", tab, string); 1796 fprintf(file, " && \n\t%s %sdisposition != MACH_MSG_TYPE_MAKE_SEND_ONCE)", tab, string); 1797 break; 1798 1799 case MACH_MSG_TYPE_MOVE_SEND: 1800 fprintf(file, " || (\n\t%s %sdisposition != MACH_MSG_TYPE_MOVE_SEND", tab, string); 1801 fprintf(file, " && \n\t%s %sdisposition != MACH_MSG_TYPE_MAKE_SEND", tab, string); 1802 fprintf(file, " && \n\t%s %sdisposition != MACH_MSG_TYPE_COPY_SEND)", tab, string); 1803 break; 1804 } 1805 } 1806 else { 1807 fprintf(file, " ||\n\t%s %sdisposition != %s", tab, string, it->itOutNameStr); 1808 } 1809 } 1810 fprintf(file, ")\n"); 1811 fprintf(file, "\t\treturn MIG_TYPE_ERROR;\n"); 1812 if (close) 1813 fprintf(file, "\t }\n\t}\n"); 1814} 1815 1816/* 1817 * argKPD_TypeCheck discipline for out-of-line types. 1818 */ 1819static void 1820WriteTCheckKPD_ool(FILE *file, register argument_t *arg) 1821{ 1822 register ipc_type_t *it = arg->argType; 1823 char *tab, string[MAX_STR_LEN]; 1824 boolean_t test; 1825 u_int howmany, howbig; 1826 1827 if (IS_MULTIPLE_KPD(it)) { 1828 WriteKPD_Iterator(file, TRUE, FALSE, arg, TRUE); 1829 tab = "\t\t\t"; 1830 sprintf(string, "ptr->"); 1831 howmany = it->itElement->itNumber; 1832 howbig = it->itElement->itSize; 1833 test = !it->itVarArray && !it->itElement->itVarArray; 1834 } 1835 else { 1836 tab = ""; 1837 sprintf(string, "In%dP->%s.", arg->argRequestPos, arg->argMsgField); 1838 howmany = it->itNumber; 1839 howbig = it->itSize; 1840 test = !it->itVarArray; 1841 } 1842 1843 fprintf(file, "\t%sif (%stype != MACH_MSG_OOL_DESCRIPTOR", tab, string); 1844 if (test) { 1845 /* if VarArray we may use no-op; if itElement->itVarArray size might change */ 1846 fprintf(file, " ||\n\t%s %ssize != %d", tab, string, (howmany * howbig + 7)/8); 1847 } 1848 1849 fprintf(file, ")\n"); 1850 fprintf(file, "\t\t%s" "return MIG_TYPE_ERROR;\n", tab); 1851 1852 if (IS_MULTIPLE_KPD(it)) 1853 fprintf(file, "\t }\n\t}\n"); 1854} 1855 1856/* 1857 * argKPD_TypeCheck discipline for out-of-line Port types. 1858 */ 1859static void 1860WriteTCheckKPD_oolport(FILE *file, register argument_t *arg) 1861{ 1862 register ipc_type_t *it = arg->argType; 1863 char *tab, string[MAX_STR_LEN]; 1864 boolean_t test; 1865 u_int howmany; 1866 char *howstr; 1867 1868 if (IS_MULTIPLE_KPD(it)) { 1869 WriteKPD_Iterator(file, TRUE, FALSE, arg, TRUE); 1870 tab = "\t"; 1871 sprintf(string, "ptr->"); 1872 howmany = it->itElement->itNumber; 1873 test = !it->itVarArray && !it->itElement->itVarArray; 1874 howstr = it->itElement->itOutNameStr; 1875 } 1876 else { 1877 tab = ""; 1878 sprintf(string, "In%dP->%s.", arg->argRequestPos, arg->argMsgField); 1879 howmany = it->itNumber; 1880 test = !it->itVarArray; 1881 howstr = it->itOutNameStr; 1882 } 1883 1884 fprintf(file, "\t%sif (%stype != MACH_MSG_OOL_PORTS_DESCRIPTOR", tab, string); 1885 if (test) 1886 /* if VarArray we may use no-op; if itElement->itVarArray size might change */ 1887 fprintf(file, " ||\n\t%s %scount != %d", tab, string, howmany); 1888 if (arg->argPoly == argNULL) 1889 fprintf(file, " ||\n\t%s %sdisposition != %s", tab, string, howstr); 1890 fprintf(file, ")\n"); 1891 fprintf(file, "\t\treturn MIG_TYPE_ERROR;\n"); 1892 1893 if (IS_MULTIPLE_KPD(it)) 1894 fprintf(file, "\t }\n\t}\n"); 1895} 1896 1897/************************************************************* 1898 * Writes code to check that the type of each of the arguments 1899 * in the reply message is what is expected. Called by 1900 * WriteRoutine for each in && typed argument in the request message. 1901 *************************************************************/ 1902static void 1903WriteTypeCheck(FILE *file, register argument_t *arg) 1904{ 1905 fprintf(file, "#if\t__MigTypeCheck\n"); 1906 (*arg->argKPD_TypeCheck)(file, arg); 1907 fprintf(file, "#endif\t/* __MigTypeCheck */\n"); 1908} 1909 1910static void 1911WritePackArgValueNormal(FILE *file, register argument_t *arg) 1912{ 1913 register ipc_type_t *it = arg->argType; 1914 1915 if (IS_VARIABLE_SIZED_UNTYPED(it) || it->itNoOptArray) { 1916 if (it->itString) { 1917 /* 1918 * Copy variable-size C string with mig_strncpy. 1919 * Save the string length (+ 1 for trailing 0) 1920 * in the argument`s count field. 1921 */ 1922 fprintf(file, "\tOutP->%s = mig_strncpy(OutP->%s, %s, %d);\n", arg->argCount->argMsgField, arg->argMsgField, arg->argVarName, it->itNumber); 1923 } 1924 else if (it->itNoOptArray) 1925 fprintf(file, "\t(void)memcpy((char *) OutP->%s, (const char *) %s, %d);\n", arg->argMsgField, arg->argVarName, it->itTypeSize); 1926 else { 1927 register argument_t *count = arg->argCount; 1928 register ipc_type_t *btype = it->itElement; 1929 identifier_t newstr; 1930 1931 /* Note btype->itNumber == count->argMultiplier */ 1932 1933 fprintf(file, "\t(void)memcpy((char *) OutP->%s, (const char *) %s, ", arg->argMsgField, arg->argVarName); 1934 if (btype->itTypeSize > 1) 1935 fprintf(file, "%d * ", btype->itTypeSize); 1936 /* count is a akbVarNeeded if arg is akbVarNeeded */ 1937 if (akCheck(count->argKind, akbVarNeeded)) 1938 newstr = count->argVarName; 1939 else 1940 newstr = (identifier_t)strconcat("OutP->", count->argMsgField); 1941 fprintf(file, "%s);\n", newstr); 1942 } 1943 } 1944 else if (it->itOutTrans != strNULL) 1945 WriteCopyType(file, it, "OutP->%s", "/* %s */ %s(%s)", arg->argMsgField, it->itOutTrans, arg->argVarName); 1946 else 1947 WriteCopyType(file, it, "OutP->%s", "/* %s */ %s", arg->argMsgField, arg->argVarName); 1948} 1949 1950static void 1951WritePackArgValueVariable(FILE *file, register argument_t *arg) 1952{ 1953 register ipc_type_t *it = arg->argType; 1954 1955 /* 1956 * only itString are treated here so far 1957 */ 1958 if (it->itString) { 1959 /* 1960 * Emit logic to call strlen to calculate the size of the argument, and ensure that it fits within the 32-bit result field 1961 * in the Reply, when targeting a 64-bit architecture. If a 32-bit architecture is the target, we emit code to just call 1962 * strlen() directly (since it'll return a 32-bit value that is guaranteed to fit). 1963 */ 1964 fputs("#ifdef __LP64__\n", file); 1965 fprintf(file, "\t{\n" 1966 "\t\t" "size_t strLength = strlen(OutP->%s) + 1;\n", arg->argMsgField); 1967 fputs( "\t\t" "if (strLength > 0xffffffff)\n" 1968 "\t\t\t" "MIG_RETURN_ERROR(OutP, MIG_BAD_ARGUMENTS);\n", file); 1969 fprintf(file, "\t\t" "OutP->%s = (mach_msg_type_number_t) strLength;\n" 1970 "\t}\n", arg->argCount->argMsgField); 1971 fputs("#else\n", file); 1972 fprintf(file, "\tOutP->%s = (mach_msg_type_number_t) strlen(OutP->%s) + 1;\n", arg->argCount->argMsgField, arg->argMsgField); 1973 fputs("#endif /* __LP64__ */\n", file); 1974 1975 } 1976} 1977 1978static void 1979WriteCopyArgValue(FILE *file, argument_t *arg) 1980{ 1981 fprintf(file, "\n"); 1982 WriteCopyType(file, arg->argType, "/* %d */ OutP->%s", "In%dP->%s", arg->argRequestPos, (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField); 1983} 1984 1985static void 1986WriteInitArgValue(FILE *file, argument_t *arg) 1987{ 1988 fprintf(file, "\n"); 1989 fprintf(file, "\tOutP->%s = %s;\n\n", arg->argMsgField, arg->argVarName); 1990} 1991 1992/* 1993 * Calculate the size of a variable-length message field. 1994 */ 1995static void 1996WriteArgSize(FILE *file, register argument_t *arg) 1997{ 1998 register ipc_type_t *ptype = arg->argType; 1999 register int bsize = ptype->itElement->itTypeSize; 2000 register argument_t *count = arg->argCount; 2001 2002 /* If the base type size of the data field isn`t a multiple of 4, 2003 we have to round up. */ 2004 if (bsize % itWordAlign != 0) 2005 fprintf(file, "_WALIGN_"); 2006 2007 /* Here, we generate ((value + %d) & ~%d). We have to put two (( at the 2008 * the beginning. 2009 */ 2010 fprintf(file, "(("); 2011 if (bsize > 1) 2012 fprintf(file, "%d * ", bsize); 2013 if (ptype->itString || !akCheck(count->argKind, akbVarNeeded)) 2014 /* get count from descriptor in message */ 2015 fprintf(file, "OutP->%s", count->argMsgField); 2016 else 2017 /* get count from argument */ 2018 fprintf(file, "%s", count->argVarName); 2019 2020 /* 2021 * If the base type size is not a multiple of sizeof(natural_t), 2022 * we have to round up. 2023 */ 2024 if (bsize % sizeof(natural_t) != 0) 2025 fprintf(file, " + %d) & ~%d)", (int)sizeof(natural_t)-1, (int)sizeof(natural_t)-1); 2026 else 2027 fprintf(file, "))"); 2028} 2029 2030/* 2031 * Adjust message size and advance reply pointer. 2032 * Called after packing a variable-length argument that 2033 * has more arguments following. 2034 */ 2035static void 2036WriteAdjustMsgSize(FILE *file, register argument_t *arg) 2037{ 2038 register routine_t *rt = arg->argRoutine; 2039 register ipc_type_t *ptype = arg->argType; 2040 2041 /* There are more Out arguments. We need to adjust msgh_size 2042 and advance OutP, so we save the size of the current field 2043 in msgh_size_delta. */ 2044 2045 fprintf(file, "\tmsgh_size_delta = "); 2046 WriteArgSize(file, arg); 2047 fprintf(file, ";\n"); 2048 2049 if (rt->rtNumReplyVar == 1) { 2050 /* We can still address the message header directly. Fill 2051 in the size field. */ 2052 2053 fprintf(file, "\tOutP->Head.msgh_size = "); 2054 rtMinReplySize(file, rt, "Reply"); 2055 fprintf(file, " + msgh_size_delta;\n"); 2056 } 2057 else if (arg->argReplyPos == 0) { 2058 /* First variable-length argument. The previous msgh_size value 2059 is the minimum reply size. */ 2060 2061 fprintf(file, "\tmsgh_size = "); 2062 rtMinReplySize(file, rt, "Reply"); 2063 fprintf(file, " + msgh_size_delta;\n"); 2064 } 2065 else 2066 fprintf(file, "\tmsgh_size += msgh_size_delta;\n"); 2067 2068 fprintf(file, "\tOutP = (Reply *) ((pointer_t) OutP + msgh_size_delta - %d);\n", ptype->itTypeSize + ptype->itPadSize); 2069} 2070 2071/* 2072 * Calculate the size of the message. Called after the 2073 * last argument has been packed. 2074 */ 2075static void 2076WriteFinishMsgSize(FILE *file, register argument_t *arg) 2077{ 2078 /* No more Out arguments. If this is the only variable Out 2079 argument, we can assign to msgh_size directly. */ 2080 2081 if (arg->argReplyPos == 0) { 2082 fprintf(file, "\tOutP->Head.msgh_size = "); 2083 rtMinReplySize(file, arg->argRoutine, "Reply"); 2084 fprintf(file, " + ("); 2085 WriteArgSize(file, arg); 2086 fprintf(file, ");\n"); 2087 } 2088 else { 2089 fprintf(file, "\tmsgh_size += "); 2090 WriteArgSize(file, arg); 2091 fprintf(file, ";\n"); 2092 } 2093} 2094 2095/* 2096 * Handle reply arguments - fill in message types and copy arguments 2097 * that need to be copied. 2098 */ 2099static void 2100WriteReplyArgs(FILE *file, register routine_t *rt) 2101{ 2102 register argument_t *arg; 2103 register argument_t *lastVarArg; 2104 2105 /* 2106 * 1. The Kernel Processed Data 2107 */ 2108 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) 2109 if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnKPD)) 2110 (*arg->argKPD_Pack)(file, arg); 2111 /* 2112 * 2. The Data Stream 2113 */ 2114 lastVarArg = argNULL; 2115 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { 2116 /* 2117 * Adjust message size and advance message pointer if 2118 * the last request argument was variable-length and the 2119 * request position will change. 2120 */ 2121 if (lastVarArg != argNULL && 2122 lastVarArg->argReplyPos < arg->argReplyPos) { 2123 WriteAdjustMsgSize(file, lastVarArg); 2124 lastVarArg = argNULL; 2125 } 2126 2127 if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnBody|akbVarNeeded)) 2128 WritePackArgValueNormal(file, arg); 2129 else if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnBody|akbVariable)) 2130 WritePackArgValueVariable(file, arg); 2131 2132 if (akCheck(arg->argKind, akbReplyCopy)) 2133 WriteCopyArgValue(file, arg); 2134 if (akCheck(arg->argKind, akbReplyInit)) 2135 WriteInitArgValue(file, arg); 2136 /* 2137 * Remember whether this was variable-length. 2138 */ 2139 if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnBody|akbVariable)) 2140 lastVarArg = arg; 2141 } 2142 /* 2143 * Finish the message size. 2144 */ 2145 if (lastVarArg != argNULL) 2146 WriteFinishMsgSize(file, lastVarArg); 2147} 2148 2149static void 2150WriteFieldDecl(FILE *file, argument_t *arg) 2151{ 2152 if (akCheck(arg->argKind, akbSendKPD) || 2153 akCheck(arg->argKind, akbReturnKPD)) 2154 WriteFieldDeclPrim(file, arg, FetchKPDType); 2155 else 2156 WriteFieldDeclPrim(file, arg, FetchServerType); 2157} 2158 2159static void 2160InitKPD_Disciplines(argument_t *args) 2161{ 2162 argument_t *arg; 2163 extern void KPD_noop(); 2164 extern void KPD_error(); 2165 extern void WriteTemplateKPD_port(); 2166 extern void WriteTemplateKPD_ool(); 2167 extern void WriteTemplateKPD_oolport(); 2168 2169 /* 2170 * WriteInitKPD_port, WriteKPD_port, WriteExtractKPD_port, 2171 * WriteInitKPD_ool, WriteKPD_ool, WriteExtractKPD_ool, 2172 * WriteInitKPD_oolport, WriteKPD_oolport, WriteExtractKPD_oolport 2173 * are local to this module (which is the reason why this initialization 2174 * takes place here rather than in utils.c). 2175 * Common routines for user and server will be established SOON, and 2176 * all of them (including the initialization) will be transfert to 2177 * utils.c 2178 * All the KPD disciplines are defaulted to be KPD_error(). 2179 * Note that akbSendKPD and akbReturnKPd are not exclusive, 2180 * because of inout type of parameters. 2181 */ 2182 for (arg = args; arg != argNULL; arg = arg->argNext) 2183 if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD)) 2184 switch (arg->argKPD_Type) { 2185 2186 case MACH_MSG_PORT_DESCRIPTOR: 2187 if akCheck(arg->argKind, akbSendKPD) { 2188 arg->argKPD_Extract = 2189 (IS_MULTIPLE_KPD(arg->argType)) ? WriteExtractKPD_port : WriteExtractArgValue; 2190 arg->argKPD_TypeCheck = WriteTCheckKPD_port; 2191 } 2192 if akCheck(arg->argKind, akbReturnKPD) { 2193 arg->argKPD_Template = WriteTemplateKPD_port; 2194 arg->argKPD_Init = WriteInitKPD_port; 2195 arg->argKPD_Pack = WriteKPD_port; 2196 } 2197 break; 2198 2199 case MACH_MSG_OOL_DESCRIPTOR: 2200 if akCheck(arg->argKind, akbSendKPD) { 2201 arg->argKPD_Extract = 2202 (IS_MULTIPLE_KPD(arg->argType)) ? WriteExtractKPD_ool : WriteExtractArgValue; 2203 arg->argKPD_TypeCheck = WriteTCheckKPD_ool; 2204 } 2205 if akCheck(arg->argKind, akbReturnKPD) { 2206 arg->argKPD_Template = WriteTemplateKPD_ool; 2207 arg->argKPD_Init = WriteInitKPD_ool; 2208 arg->argKPD_Pack = WriteKPD_ool; 2209 } 2210 break; 2211 2212 case MACH_MSG_OOL_PORTS_DESCRIPTOR: 2213 if akCheck(arg->argKind, akbSendKPD) { 2214 arg->argKPD_Extract = 2215 (IS_MULTIPLE_KPD(arg->argType)) ? WriteExtractKPD_oolport : WriteExtractArgValue; 2216 arg->argKPD_TypeCheck = WriteTCheckKPD_oolport; 2217 } 2218 if akCheck(arg->argKind, akbReturnKPD) { 2219 arg->argKPD_Template = WriteTemplateKPD_oolport; 2220 arg->argKPD_Init = WriteInitKPD_oolport; 2221 arg->argKPD_Pack = WriteKPD_oolport; 2222 } 2223 break; 2224 2225 default: 2226 printf("MiG internal error: type of kernel processed data unknown\n"); 2227 exit(1); 2228 } /* end of switch */ 2229} 2230 2231static void WriteStringTerminatorCheck(FILE *file, routine_t *rt) 2232{ 2233 // generate code to verify that the length of a C string is not greater than the size of the 2234 // buffer in which it is stored. 2235 argument_t *argPtr; 2236 int msg_limit_calculated = FALSE; 2237 int found_string_argument = FALSE; 2238 int variable_length_args_present = (rt->rtMaxRequestPos > 0); 2239 2240 // scan through arguments to see if there are any strings 2241 for (argPtr = rt->rtArgs; argPtr != NULL; argPtr = argPtr->argNext) { 2242 if ((argPtr->argKind & akbRequest) && argPtr->argType->itString) { 2243 found_string_argument = TRUE; 2244 break; 2245 } 2246 } 2247 2248 if (found_string_argument) { 2249 // create a new scope, for local variables 2250 fputs("#if __MigTypeCheck\n" "\t" "{" "\n", file); 2251 2252 for (argPtr = rt->rtArgs; argPtr != NULL; argPtr = argPtr->argNext) { 2253 if ((argPtr->argKind & akbRequest) && argPtr->argType->itString) { 2254 //fprintf(stderr, "### found itString: variable name = %s, max length = %d\n", argPtr->argName, argPtr->argType->itNumber); 2255 2256 if (!msg_limit_calculated) { 2257 msg_limit_calculated = TRUE; // only need to do this once 2258 fputs("\t\t" "char * msg_limit = ((char *) In0P) + In0P->Head.msgh_size;\n", file); 2259 if (IsKernelServer) { 2260 fputs("#if __MigKernelSpecificCode\n", file); 2261 fputs("\t\t" "size_t strnlen_limit;" "\n", file); 2262 fputs("#else\n", file); 2263 } 2264 fputs("\t\t" "size_t memchr_limit;" "\n", file); 2265 if (IsKernelServer) { 2266 fputs("#endif /* __MigKernelSpecificCode */" "\n", file); 2267 } 2268 fputc('\n', file); 2269 } 2270 2271 // I would really prefer to use strnlen() here, to ensure that the byte scanning logic does not extend beyond 2272 // the end of the buffer, but it's not necessarily guaranteed to be available. Instead, I'll use memchr(), 2273 // and let it look for the terminating null byte. 2274 // (later...) 2275 // It turns out that the kernel does not have memchr() available, but strnlen() IS available, so we'll just 2276 // have to emit some conditional code to use the appropriate runtime environment scanning function. 2277 // 2278 if (IsKernelServer) { 2279 fputs("#if __MigKernelSpecificCode\n", file); 2280 fputs("\t\t" "strnlen_limit = min((msg_limit - ", file); 2281 // If there are variable-length arguments within the message, the proper (adjusted) 2282 // pointers must be used to access those strings 2283 fprintf(file, "In%dP->%s), %d);" "\n", (variable_length_args_present ? argPtr->argRequestPos : 0), argPtr->argName, argPtr->argType->itNumber); 2284 fputs("\t\t" "if (", file); 2285 fprintf(file, "( strnlen(In%dP->%s, strnlen_limit) >= %d + 1 )", (variable_length_args_present ? argPtr->argRequestPos : 0), argPtr->argName, argPtr->argType->itNumber); 2286 fputs(")" "\n" "\t\t\t" "return MIG_BAD_ARGUMENTS; // string length exceeds buffer length!" "\n", file); 2287 fputs("#else\n", file); 2288 } 2289 // If there are variable-length arguments within the message, the proper (adjusted) 2290 // pointers must be used to access those strings 2291 fprintf(file, "\t\t" "memchr_limit = min((msg_limit - In%dP->%s), %d);" "\n", (variable_length_args_present ? argPtr->argRequestPos : 0), argPtr->argName, argPtr->argType->itNumber); 2292 fputs("\t\t" "if (", file); 2293 fprintf(file, "( memchr(In%dP->%s, '\\0', memchr_limit) == NULL )", (variable_length_args_present ? argPtr->argRequestPos : 0), argPtr->argName); 2294 fputs(")" "\n" "\t\t\t" "return MIG_BAD_ARGUMENTS; // string length exceeds buffer length!" "\n", file); 2295 if (IsKernelServer) { 2296 fputs("#endif /* __MigKernelSpecificCode */" "\n", file); 2297 } 2298 } 2299 } 2300 fputs("\t" "}" "\n" "#endif" "\t" "/* __MigTypeCheck */" "\n\n", file); // terminate new scope 2301 } 2302 2303 return; 2304} 2305 2306static void 2307WriteOOLSizeCheck(FILE *file, routine_t *rt) 2308{ 2309 /* Emit code to validate the actual size of ool data vs. the reported size */ 2310 2311 argument_t *argPtr; 2312 boolean_t openedTypeCheckConditional = FALSE; 2313 2314 // scan through arguments to see if there are any ool data blocks 2315 for (argPtr = rt->rtArgs; argPtr != NULL; argPtr = argPtr->argNext) { 2316 if (akCheck(argPtr->argKind, akbSendKPD) && (argPtr->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR)) { 2317 register ipc_type_t *it = argPtr->argType; 2318 char *tab, string[MAX_STR_LEN]; 2319 boolean_t test; 2320 argument_t *argCountPtr; 2321 2322 if ( !openedTypeCheckConditional ) { 2323 openedTypeCheckConditional = TRUE; 2324 fputs("#if __MigTypeCheck\n", file); 2325 } 2326 2327 if (IS_MULTIPLE_KPD(it)) { 2328 WriteKPD_Iterator(file, TRUE, FALSE, argPtr, TRUE); 2329 tab = "\t\t\t"; 2330 sprintf(string, "ptr->"); 2331 test = !it->itVarArray && !it->itElement->itVarArray; 2332 it = it->itElement; // point to element descriptor, so size calculation is correct 2333 argCountPtr = argPtr->argSubCount; 2334 } 2335 else { 2336 tab = ""; 2337 sprintf(string, "In%dP->%s.", argPtr->argRequestPos, argPtr->argMsgField); 2338 test = !it->itVarArray; 2339 argCountPtr = argPtr->argCount; 2340 } 2341 2342 if (!test) { 2343 int multiplier = (argCountPtr->argMultiplier > 1 || it->itSize > 8) ? argCountPtr->argMultiplier * it->itSize / 8 : 1; 2344 fprintf(file, "\t%s" "if (%ssize ", tab, string); 2345 if (multiplier > 1) 2346 fprintf(file, "/ %d ", multiplier); 2347 fprintf(file,"!= In%dP->%s%s)\n", argCountPtr->argRequestPos, argCountPtr->argVarName, IS_MULTIPLE_KPD(it) ? "[i]" : ""); 2348 2349 fprintf(file, "\t\t%s" "return MIG_TYPE_ERROR;\n", tab); 2350 } 2351 2352 if (IS_MULTIPLE_KPD(it)) 2353 fprintf(file, "\t }\n\t}\n"); 2354 2355 } 2356 } 2357 2358 if ( openedTypeCheckConditional ) 2359 fputs("#endif" "\t" "/* __MigTypeCheck */" "\n\n", file); 2360} 2361 2362 2363void 2364WriteCheckRequest(FILE *file, routine_t *rt) 2365{ 2366 int i; 2367 2368 /* initialize the disciplines for the handling of KPDs */ 2369 InitKPD_Disciplines(rt->rtArgs); 2370 2371 fprintf(file, "\n"); 2372 fprintf(file, "#if ( __MigTypeCheck "); 2373 if (CheckNDR) 2374 fprintf(file, "|| __NDR_convert__ "); 2375 fprintf(file, ")\n"); 2376 fprintf(file, "#if __MIG_check__Request__%s_subsystem__\n", SubsystemName); 2377 fprintf(file, "#if !defined(__MIG_check__Request__%s_t__defined)\n", rt->rtName); 2378 fprintf(file, "#define __MIG_check__Request__%s_t__defined\n", rt->rtName); 2379 if (CheckNDR && akCheck(rt->rtNdrCode->argKind, akbRequest)) { 2380 WriteList(file, rt->rtArgs, WriteRequestNDRConvertIntRepArgDecl, akbSendNdr, "", ""); 2381 WriteList(file, rt->rtArgs, WriteRequestNDRConvertCharRepArgDecl, akbSendNdr, "", ""); 2382 WriteList(file, rt->rtArgs, WriteRequestNDRConvertFloatRepArgDecl, akbSendNdr, "", ""); 2383 } 2384 fprintf(file, "\n"); 2385 fprintf(file, "mig_internal kern_return_t __MIG_check__Request__%s_t(__attribute__((__unused__)) __Request__%s_t *In0P", rt->rtName, rt->rtName); 2386 for (i = 1; i <= rt->rtMaxRequestPos; i++) 2387 fprintf(file, ", __attribute__((__unused__)) __Request__%s_t **In%dPP", rt->rtName, i); 2388 fprintf(file, ")\n{\n"); 2389 2390 fprintf(file, "\n\ttypedef __Request__%s_t __Request;\n", rt->rtName); 2391 for (i = 1; i <= rt->rtMaxRequestPos; i++) 2392 fprintf(file, "\t__Request *In%dP;\n", i); 2393 if (rt->rtNumRequestVar > 0) { 2394 fprintf(file, "#if\t__MigTypeCheck\n"); 2395 fprintf(file, "\tunsigned int msgh_size;\n"); 2396 fprintf(file, "#endif\t/* __MigTypeCheck */\n"); 2397 } 2398 if (rt->rtMaxRequestPos > 0) 2399 fprintf(file, "\tunsigned int msgh_size_delta;\n"); 2400 if (rt->rtNumRequestVar > 0 || rt->rtMaxRequestPos > 0) 2401 fprintf(file, "\n"); 2402 2403 WriteCheckHead(file, rt); 2404 2405 WriteList(file, rt->rtArgs, WriteTypeCheck, akbSendKPD, "\n", "\n"); 2406 2407 { 2408 argument_t *arg, *lastVarArg; 2409 2410 lastVarArg = argNULL; 2411 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) { 2412 if (lastVarArg != argNULL && 2413 lastVarArg->argRequestPos < arg->argRequestPos) { 2414 WriteAdjustRequestMsgPtr(file, lastVarArg); 2415 lastVarArg = argNULL; 2416 } 2417 if (akCheckAll(arg->argKind, akbSendRcv|akbSendBody)) { 2418 if (akCheck(arg->argKind, akbVariable)) { 2419 WriteCheckMsgSize(file, arg); 2420 lastVarArg = arg; 2421 } 2422 } 2423 } 2424 } 2425 2426 if (CheckNDR && akCheck(rt->rtNdrCode->argKind, akbRequest)) { 2427 fprintf(file, "#if\t"); 2428 WriteList(file, rt->rtArgs, WriteRequestNDRConvertIntRepArgCond, akbSendNdr, " || \\\n\t", "\n"); 2429 fprintf(file, "\tif (In0P->NDR.int_rep != NDR_record.int_rep) {\n"); 2430 WriteList(file, rt->rtArgs, WriteRequestNDRConvertIntRepArgUse, akbSendNdr, "", ""); 2431 fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__int_rep...) */\n\n"); 2432 2433 WriteOOLSizeCheck(file, rt); 2434 2435 fprintf(file, "#if\t"); 2436 WriteList(file, rt->rtArgs, WriteRequestNDRConvertCharRepArgCond, akbSendNdr, " || \\\n\t", "\n"); 2437 fprintf(file, "\tif (In0P->NDR.char_rep != NDR_record.char_rep) {\n"); 2438 WriteList(file, rt->rtArgs, WriteRequestNDRConvertCharRepArgUse, akbSendNdr, "", ""); 2439 fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__char_rep...) */\n\n"); 2440 2441 fprintf(file, "#if\t"); 2442 WriteList(file, rt->rtArgs, WriteRequestNDRConvertFloatRepArgCond, akbSendNdr, " || \\\n\t", "\n"); 2443 fprintf(file, "\tif (In0P->NDR.float_rep != NDR_record.float_rep) {\n"); 2444 WriteList(file, rt->rtArgs, WriteRequestNDRConvertFloatRepArgUse, akbSendNdr, "", ""); 2445 fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__float_rep...) */\n\n"); 2446 } else { 2447 WriteOOLSizeCheck(file, rt); 2448 } 2449 2450 WriteStringTerminatorCheck(file, rt); 2451 2452 fprintf(file, "\treturn MACH_MSG_SUCCESS;\n"); 2453 fprintf(file, "}\n"); 2454 fprintf(file, "#endif /* !defined(__MIG_check__Request__%s_t__defined) */\n", rt->rtName); 2455 fprintf(file, "#endif /* __MIG_check__Request__%s_subsystem__ */\n", SubsystemName); 2456 fprintf(file, "#endif /* ( __MigTypeCheck "); 2457 if (CheckNDR) 2458 fprintf(file, "|| __NDR_convert__ "); 2459 fprintf(file, ") */\n"); 2460 fprintf(file, "\n"); 2461} 2462 2463void 2464WriteCheckRequestCall(FILE *file, routine_t *rt) 2465{ 2466 int i; 2467 2468 fprintf(file, "\n"); 2469 fprintf(file, "#if\tdefined(__MIG_check__Request__%s_t__defined)\n", rt->rtName); 2470 fprintf(file, "\tcheck_result = __MIG_check__Request__%s_t((__Request *)In0P", rt->rtName); 2471 for (i = 1; i <= rt->rtMaxRequestPos; i++) 2472 fprintf(file, ", (__Request **)&In%dP", i); 2473 fprintf(file, ");\n"); 2474 fprintf(file, "\tif (check_result != MACH_MSG_SUCCESS)\n"); 2475 fprintf(file, "\t\t{ MIG_RETURN_ERROR(OutP, check_result); }\n"); 2476 fprintf(file, "#endif\t/* defined(__MIG_check__Request__%s_t__defined) */\n", rt->rtName); 2477 fprintf(file, "\n"); 2478} 2479 2480void 2481WriteCheckRequests(FILE *file, statement_t *stats) 2482{ 2483 statement_t *stat; 2484 2485 for (stat = stats; stat != stNULL; stat = stat->stNext) 2486 if (stat->stKind == skRoutine) 2487 WriteCheckRequest(file, stat->stRoutine); 2488} 2489 2490static void 2491WriteRoutine(FILE *file, register routine_t *rt) 2492{ 2493 /* Declare the server work function: */ 2494 if (ServerHeaderFileName == strNULL) 2495 WriteServerRoutine(file, rt); 2496 2497 fprintf(file, "\n"); 2498 2499 fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName); 2500 fprintf(file, "mig_internal novalue _X%s\n", rt->rtName); 2501 if (BeAnsiC) { 2502 fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n"); 2503 } 2504 else { 2505 fprintf(file, "#if\t%s\n", NewCDecl); 2506 fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n"); 2507 fprintf(file, "#else\n"); 2508 fprintf(file, "\t(InHeadP, OutHeadP)\n"); 2509 fprintf(file, "\tmach_msg_header_t *InHeadP, *OutHeadP;\n"); 2510 fprintf(file, "#endif\t/* %s */\n", NewCDecl); 2511 } 2512 2513 fprintf(file, "{\n"); 2514 WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbRequest, "Request", rt->rtSimpleRequest, TRUE, rt->rtServerImpl, FALSE); 2515 fprintf(file, "\ttypedef __Request__%s_t __Request;\n", rt->rtName); 2516 fprintf(file, "\ttypedef __Reply__%s_t Reply;\n\n", rt->rtName); 2517 2518 /* 2519 * Define a Minimal Reply structure to be used in case of errors 2520 */ 2521 fprintf(file, "\t/*\n"); 2522 fprintf(file, "\t * typedef struct {\n"); 2523 fprintf(file, "\t * \tmach_msg_header_t Head;\n"); 2524 fprintf(file, "\t * \tNDR_record_t NDR;\n"); 2525 fprintf(file, "\t * \tkern_return_t RetCode;\n"); 2526 fprintf(file, "\t * } mig_reply_error_t;\n"); 2527 fprintf(file, "\t */\n"); 2528 fprintf(file, "\n"); 2529 2530 WriteVarDecls(file, rt); 2531 2532 if (IsKernelServer) { 2533 fprintf(file, "#if\t__MigKernelSpecificCode\n"); 2534 WriteList(file, rt->rtArgs, WriteTemplateDeclOut, akbReturnKPD, "\n", "\n"); 2535 fprintf(file, "#else\n"); 2536 } 2537 WriteList(file, rt->rtArgs, WriteTemplateDeclIn, akbReturnKPD, "\n", "\n"); 2538 if (IsKernelServer) { 2539 fprintf(file, "#endif /* __MigKernelSpecificCode */\n"); 2540 } 2541 WriteRetCode(file, rt->rtRetCode); 2542 WriteList(file, rt->rtArgs, WriteLocalVarDecl, akbVarNeeded | akbServerArg, ";\n", ";\n\n"); 2543 WriteApplMacro(file, "Rcv", "Declare", rt); 2544 WriteApplMacro(file, "Rcv", "Before", rt); 2545 if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) { 2546 WriteRetCArgCheckError(file, rt); 2547 if (rt->rtServerImpl) 2548 WriteCheckTrailerHead(file, rt, FALSE); 2549 WriteServerCall(file, rt, WriteConditionalCallArg); 2550 WriteRetCArgFinishError(file, rt); 2551 } 2552 2553 WriteCheckRequestCall(file, rt); 2554 WriteCheckRequestTrailerArgs(file, rt); 2555 2556 /* 2557 * Initialize the KPD records in the Reply structure with the 2558 * templates. We do this beforehand because the call to the procedure 2559 * will overwrite some of the values (after the call it would be impossible 2560 * to initialize the KPD records from the static Templates, because we 2561 * would lose data). 2562 */ 2563 WriteList(file, rt->rtArgs, WriteInitKPDValue, akbReturnKPD, "\n", "\n"); 2564 2565 WriteList(file, rt->rtArgs, WriteExtractArg, akbNone, "", ""); 2566 2567 if (UseEventLogger) 2568 WriteLogMsg(file, rt, LOG_SERVER, LOG_REQUEST); 2569 2570 WriteServerCall(file, rt, WriteServerCallArg); 2571 2572 WriteReverseList(file, rt->rtArgs, WriteDestroyArg, akbDestroy, "", ""); 2573 2574 /* 2575 * For one-way routines, it doesn`t make sense to check the return 2576 * code, because we return immediately afterwards. However, 2577 * kernel servers may want to deallocate port arguments - and the 2578 * deallocation must not be done if the return code is not KERN_SUCCESS. 2579 */ 2580 if (rt->rtOneWay || rt->rtNoReplyArgs) { 2581 if (IsKernelServer) { 2582 fprintf(file,"#if\t__MigKernelSpecificCode\n"); 2583 if (rtCheckMaskFunction(rt->rtArgs, akbSendKPD, CheckDestroyPortArg)) { 2584 WriteCheckReturnValue(file, rt); 2585 } 2586 WriteReverseList(file, rt->rtArgs, WriteDestroyPortArg, akbSendKPD, "", ""); 2587 fprintf(file,"#endif /* __MigKernelSpecificCode */\n"); 2588 } 2589 /* although we have an empty reply, we still have to make sure that 2590 some fields such as NDR get properly initialized */ 2591 if (!rt->rtOneWay) 2592 WriteList(file, rt->rtArgs, WriteInitArgValue, akbReplyInit, "\n", "\n"); 2593 } 2594 else { 2595 WriteCheckReturnValue(file, rt); 2596 2597 if (IsKernelServer) { 2598 fprintf(file,"#if\t__MigKernelSpecificCode\n"); 2599 WriteReverseList(file, rt->rtArgs, WriteDestroyPortArg, akbSendKPD, "", ""); 2600 fprintf(file,"#endif /* __MigKernelSpecificCode */\n"); 2601 } 2602 WriteReplyArgs(file, rt); 2603 WriteReplyInit(file, rt); 2604 if (!rt->rtSimpleReply) 2605 fprintf(file, "\tOutP->msgh_body.msgh_descriptor_count = %d;\n", rt->rtReplyKPDs); 2606 } 2607 if (UseEventLogger) 2608 WriteLogMsg(file, rt, LOG_SERVER, LOG_REPLY); 2609 2610 WriteApplMacro(file, "Rcv", "After", rt); 2611 fprintf(file, "}\n"); 2612} 2613 2614void 2615WriteServer(FILE *file, statement_t *stats) 2616{ 2617 register statement_t *stat; 2618 2619 WriteProlog(file, stats); 2620 if (BeAnsiC) 2621 WriteForwardDeclarations(file, stats); 2622 for (stat = stats; stat != stNULL; stat = stat->stNext) 2623 switch (stat->stKind) { 2624 2625 case skRoutine: 2626 WriteCheckRequest(file, stat->stRoutine); 2627 WriteRoutine(file, stat->stRoutine); 2628 break; 2629 2630 case skIImport: 2631 case skImport: 2632 case skSImport: 2633 case skDImport: 2634 case skUImport: 2635 break; 2636 2637 default: 2638 fatal("WriteServer(): bad statement_kind_t (%d)", 2639 (int) stat->stKind); 2640 } 2641 WriteDispatcher(file, stats); 2642} 2643