| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | |
| 3 * Use of this source code is governed by a BSD-style license that can be | |
| 4 * found in the LICENSE file. | |
| 5 */ | |
| 6 | |
| 7 /* Validator to check that instructions are in the legal subset. */ | |
| 8 | |
| 9 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/nc_illegal.h" | |
| 10 | |
| 11 #include "native_client/src/shared/platform/nacl_log.h" | |
| 12 #include "native_client/src/trusted/validator/x86/decoder/ncop_exps.h" | |
| 13 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_iter.h" | |
| 14 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state.h" | |
| 15 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_internal
.h" | |
| 16 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter.
h" | |
| 17 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter_
internal.h" | |
| 18 #include "native_client/src/trusted/validator/x86/decoder/generator/gen/nacl_dis
allows.h" | |
| 19 | |
| 20 /* To turn on debugging of instruction decoding, change value of | |
| 21 * DEBUGGING to 1. | |
| 22 */ | |
| 23 #define DEBUGGING 0 | |
| 24 | |
| 25 #include "native_client/src/shared/utils/debugging.h" | |
| 26 | |
| 27 /* Message to use if we don't have a more precise reason why the instruction | |
| 28 * is illegal. | |
| 29 */ | |
| 30 static const char* kNaClGenericReasonDisallowed = | |
| 31 "Illegal native client instruction"; | |
| 32 | |
| 33 /* This function returns a printable description of the reason an instruction | |
| 34 * is disallowed, or NULL if the reason is not understood. | |
| 35 */ | |
| 36 static const char* NaClReasonWhyDisallowed(NaClDisallowsFlag flag) { | |
| 37 switch (flag) { | |
| 38 case NaClTooManyPrefixBytes: | |
| 39 return "More than one (non-REX) prefix byte specified"; | |
| 40 case NaClMarkedIllegal: | |
| 41 return "This instruction has been marked illegal by Native Client"; | |
| 42 case NaClMarkedInvalid: | |
| 43 return "Opcode sequence doesn't define a valid x86 instruction"; | |
| 44 case NaClMarkedSystem: | |
| 45 return "System instructions are not allowed by Native Client"; | |
| 46 case NaClHasBadSegmentPrefix: | |
| 47 return "Uses a segment prefix byte not allowed by Native Client"; | |
| 48 case NaClCantUsePrefix67: | |
| 49 return "Use of 67 (ADDR16) prefix not allowed by Native Client"; | |
| 50 case NaClMultipleRexPrefix: | |
| 51 return "Multiple use of REX prefix not allowed"; | |
| 52 case NaClRepDisallowed: | |
| 53 return | |
| 54 "Use of REP (F3) prefix for instruction not allowed by " | |
| 55 "Native Client"; | |
| 56 case NaClRepneDisallowed: | |
| 57 return | |
| 58 "Use of REPNE (F2) prefix for instruction not allowed by " | |
| 59 "Native Client"; | |
| 60 case NaClData16Disallowed: | |
| 61 return | |
| 62 "Use of DATA16 (66) prefix for instruction not allowed by " | |
| 63 "Native Client"; | |
| 64 case NaClHasDuplicatePrefix: | |
| 65 return | |
| 66 "Duplicating a prefix byte is not allowed by Native Client"; | |
| 67 case NaClHasAmbigSegmentPrefixes: | |
| 68 return | |
| 69 "Specifying different segment registers using prefix bytes " | |
| 70 "is not allowed by Native Client"; | |
| 71 case NaClRexPrefixNotLast: | |
| 72 return "REX prefix byte must appear last"; | |
| 73 default: | |
| 74 return NULL; | |
| 75 } | |
| 76 } | |
| 77 | |
| 78 /* Same as NaClReasonWhyDisallowed, except that the unknown value (NULL) | |
| 79 * is replaced by a useful print error message. | |
| 80 */ | |
| 81 static const char* NaClGetReasonWhyDisallowed(NaClDisallowsFlag flag) { | |
| 82 const char* why = NaClReasonWhyDisallowed(flag); | |
| 83 if (NULL == why) { | |
| 84 /* If reached, we don't understand the flag. Non the less, we should | |
| 85 * return a message explaining that the instruction is illegal, so | |
| 86 * that an appropriate error message can be printed. | |
| 87 */ | |
| 88 why = kNaClGenericReasonDisallowed; | |
| 89 } | |
| 90 return why; | |
| 91 } | |
| 92 | |
| 93 /* A mask of possible segment prefixes. */ | |
| 94 static const uint32_t kNaClSegmentPrefixMask = | |
| 95 kPrefixSEGES | kPrefixSEGFS | kPrefixSEGGS | kPrefixSEGSS | | |
| 96 kPrefixSEGCS | kPrefixSEGDS; | |
| 97 | |
| 98 /* | |
| 99 * A mask for prefixes that can't appear with any jump instruction. | |
| 100 * Note: We rule these out because of Intel's Software Developer's | |
| 101 * Manual (volume 2a) documents in section 2.1.1 that such uses may | |
| 102 * cause unpredictable behaviour. | |
| 103 */ | |
| 104 static const uint32_t kNaClUnsafeJumpPrefixes = | |
| 105 kPrefixSEGES | kPrefixSEGFS | kPrefixSEGGS | kPrefixSEGSS; | |
| 106 | |
| 107 /* | |
| 108 * A mask for prefixes that can only appear with conditional jump | |
| 109 * instructions with branch hints. | |
| 110 */ | |
| 111 static const uint32_t kNaClBranchHintJumpPrefixes = | |
| 112 kPrefixSEGCS | kPrefixSEGDS; | |
| 113 | |
| 114 /* This function checks properties about segment registers on an | |
| 115 * instruction, reporting issues not allowed by native client. | |
| 116 */ | |
| 117 static void NaClCheckSegmentPrefixes(NaClValidatorState* state, | |
| 118 Bool* is_legal, | |
| 119 NaClDisallowsFlags* disallows_flags) { | |
| 120 NaClInstState* inst_state = state->cur_inst_state; | |
| 121 Bool segment_prefixes_ok = TRUE; | |
| 122 | |
| 123 if (0 == (inst_state->prefix_mask & kNaClSegmentPrefixMask)) return; | |
| 124 | |
| 125 if (state->cur_inst->flags & | |
| 126 (NACL_IFLAG(JumpInstruction) | NACL_IFLAG(ConditionalJump))) { | |
| 127 if (inst_state->prefix_mask & kNaClUnsafeJumpPrefixes) { | |
| 128 segment_prefixes_ok = FALSE; | |
| 129 } | |
| 130 if (NaClExcludesBit(state->cur_inst->flags, NACL_IFLAG(BranchHints)) && | |
| 131 NaClHasBit(inst_state->prefix_mask, kNaClBranchHintJumpPrefixes)) { | |
| 132 segment_prefixes_ok = FALSE; | |
| 133 } | |
| 134 } else { | |
| 135 /* We don't allow any prefix masks on data accesses. */ | |
| 136 segment_prefixes_ok = FALSE; | |
| 137 } | |
| 138 | |
| 139 if (!segment_prefixes_ok) { | |
| 140 *is_legal = FALSE; | |
| 141 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClHasBadSegmentPrefix); | |
| 142 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
| 143 NaClGetReasonWhyDisallowed(NaClHasBadSegmentPrefix))); | |
| 144 } | |
| 145 | |
| 146 /* Don't allow ambiguous prefix forms. */ | |
| 147 if (inst_state->has_ambig_segment_prefixes) { | |
| 148 *is_legal = FALSE; | |
| 149 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClHasAmbigSegmentPrefixes); | |
| 150 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
| 151 NaClGetReasonWhyDisallowed(NaClHasAmbigSegmentPrefixes))); | |
| 152 } | |
| 153 | |
| 154 } | |
| 155 | |
| 156 /* This function checks properties of prefix bytes on an instruction, | |
| 157 * reporting issues not allowed by native client. | |
| 158 * | |
| 159 * Parameters are: | |
| 160 * state : The current validator state to check. | |
| 161 * is_legal: Flag set to FALSE if any prefix problems are found. | |
| 162 * disallows_flags : Set of flags, describing the reason(s) the | |
| 163 * current instruction in the validator state is not | |
| 164 * legal in native client. Updated as appropriate. | |
| 165 */ | |
| 166 static void NaClCheckForPrefixIssues(NaClValidatorState* state, | |
| 167 Bool* is_legal, | |
| 168 NaClDisallowsFlags* disallows_flags) { | |
| 169 NaClInstState* inst_state = state->cur_inst_state; | |
| 170 const NaClInst* inst = state->cur_inst; | |
| 171 /* Don't allow more than one (non-REX) prefix. */ | |
| 172 int num_prefix_bytes = inst_state->num_prefix_bytes; | |
| 173 if (inst_state->rexprefix) --num_prefix_bytes; | |
| 174 | |
| 175 /* Don't allow an invalid instruction. */ | |
| 176 if (!NaClInstStateIsValid(inst_state)) { | |
| 177 *is_legal = FALSE; | |
| 178 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClMarkedInvalid); | |
| 179 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
| 180 NaClGetReasonWhyDisallowed(NaClMarkedInvalid))); | |
| 181 } | |
| 182 | |
| 183 /* If there aren't prefix bytes, there isn't anything to check. */ | |
| 184 if (num_prefix_bytes == 0) return; | |
| 185 | |
| 186 /* Don't allow multiple prefix bytes, except for the special | |
| 187 * case of the pair DATA16 and LOCK (allowed so that one can | |
| 188 * lock short integers). | |
| 189 * | |
| 190 * Note: Explicit NOP sequences that use multiple 66 values are | |
| 191 * recognized as special cases, and need not be processed here. | |
| 192 */ | |
| 193 if (num_prefix_bytes > 1) { | |
| 194 if ((num_prefix_bytes == 2) && | |
| 195 (inst_state->prefix_mask & kPrefixDATA16) && | |
| 196 (inst_state->prefix_mask & kPrefixLOCK)) { | |
| 197 /* Allow data prefix if lock prefix also given. */ | |
| 198 } else { | |
| 199 *is_legal = FALSE; | |
| 200 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClTooManyPrefixBytes); | |
| 201 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
| 202 NaClGetReasonWhyDisallowed(NaClTooManyPrefixBytes))); | |
| 203 } | |
| 204 } | |
| 205 | |
| 206 /* Only allow REP/REPE/REPZ (F3) prefix if flag specifies it is allowed. */ | |
| 207 if ((inst_state->prefix_mask & kPrefixREP) && | |
| 208 (NACL_EMPTY_IFLAGS == (inst->flags & NACL_IFLAG(OpcodeAllowsRep)))) { | |
| 209 *is_legal = FALSE; | |
| 210 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClRepDisallowed); | |
| 211 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
| 212 NaClGetReasonWhyDisallowed(NaClRepDisallowed))); | |
| 213 } | |
| 214 | |
| 215 /* Only allow REPNE/REPNZ (F2) prefix if flag specifies it is allowed. */ | |
| 216 if ((inst_state->prefix_mask & kPrefixREPNE) && | |
| 217 (NACL_EMPTY_IFLAGS == (inst->flags & NACL_IFLAG(OpcodeAllowsRepne)))) { | |
| 218 *is_legal = FALSE; | |
| 219 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClRepneDisallowed); | |
| 220 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
| 221 NaClGetReasonWhyDisallowed(NaClRepneDisallowed))); | |
| 222 } | |
| 223 | |
| 224 /* Only allow Data16 (66) prefix if flag specifies it is allowed. */ | |
| 225 if ((inst_state->prefix_mask & kPrefixDATA16) && | |
| 226 (NACL_EMPTY_IFLAGS == (inst->flags & NACL_IFLAG(OpcodeAllowsData16)))) { | |
| 227 *is_legal = FALSE; | |
| 228 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClData16Disallowed); | |
| 229 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
| 230 NaClGetReasonWhyDisallowed(NaClData16Disallowed))); | |
| 231 } | |
| 232 | |
| 233 /* Don't allow more than one REX prefix. */ | |
| 234 if (inst_state->num_rex_prefixes > 1) { | |
| 235 /* NOTE: does not apply to NOP, since they are parsed using | |
| 236 * special handling (i.e. explicit byte sequence matches) that | |
| 237 * doesn't explicitly define prefix bytes. | |
| 238 * | |
| 239 * NOTE: We don't disallow this while decoding, since xed doesn't | |
| 240 * disallow this, and we want to be able to compare our tool | |
| 241 * to xed. | |
| 242 */ | |
| 243 *is_legal = FALSE; | |
| 244 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClMultipleRexPrefix); | |
| 245 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
| 246 NaClGetReasonWhyDisallowed(NaClMultipleRexPrefix))); | |
| 247 } | |
| 248 | |
| 249 /* Don't allow shortened address sizes. That is prefix ADDR16. */ | |
| 250 if (inst_state->prefix_mask & kPrefixADDR16) { | |
| 251 *is_legal = FALSE; | |
| 252 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClCantUsePrefix67); | |
| 253 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
| 254 NaClGetReasonWhyDisallowed(NaClCantUsePrefix67))); | |
| 255 } | |
| 256 | |
| 257 NaClCheckSegmentPrefixes(state, is_legal, disallows_flags); | |
| 258 | |
| 259 /* Don't allow duplicated prefixes. Note: Don't report if multiple | |
| 260 * REX prefixes has been reported, since we don't know what duplicates | |
| 261 * caused the problem, and an error has already been reported. | |
| 262 */ | |
| 263 if (inst_state->has_prefix_duplicates && | |
| 264 (NACL_EMPTY_DISALLOWS_FLAGS == | |
| 265 (*disallows_flags & NACL_DISALLOWS_FLAG(NaClMultipleRexPrefix)))) { | |
| 266 /* NOTE: does not apply to NOP, since they are parsed using | |
| 267 * special handling (i.e. explicit byte sequence matches) that | |
| 268 * doesn't explicitly define prefix bytes. | |
| 269 * | |
| 270 * NOTE: We don't disallow this while decoding, since xed doesn't | |
| 271 * disallow this, and we want to be able to compare our tool | |
| 272 * to xed. | |
| 273 */ | |
| 274 *is_legal = FALSE; | |
| 275 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClHasDuplicatePrefix); | |
| 276 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
| 277 NaClGetReasonWhyDisallowed(NaClHasDuplicatePrefix))); | |
| 278 } | |
| 279 | |
| 280 /* Check the location of the REX prefix, if one is specified.. */ | |
| 281 if (inst_state->prefix_mask & kPrefixREX) { | |
| 282 /* First find the locations of the REX prefix. */ | |
| 283 int i; | |
| 284 int rex_index = -1; | |
| 285 for (i = 0; i < inst_state->num_prefix_bytes; ++i) { | |
| 286 char prefix = inst_state->bytes.byte[i]; | |
| 287 switch (prefix) { | |
| 288 case 0x40: | |
| 289 case 0x41: | |
| 290 case 0x42: | |
| 291 case 0x43: | |
| 292 case 0x44: | |
| 293 case 0x45: | |
| 294 case 0x46: | |
| 295 case 0x47: | |
| 296 case 0x48: | |
| 297 case 0x49: | |
| 298 case 0x4a: | |
| 299 case 0x4b: | |
| 300 case 0x4c: | |
| 301 case 0x4d: | |
| 302 case 0x4e: | |
| 303 case 0x4f: | |
| 304 rex_index = i; | |
| 305 break; | |
| 306 default: | |
| 307 break; | |
| 308 } | |
| 309 } | |
| 310 /* NOTE: REX prefix must be last, unless FO exists. If FO | |
| 311 * exists, it must be after REX (Intel Manual). | |
| 312 * | |
| 313 * NOTE: (karl) It appears that this constraint is violated | |
| 314 * with compiled code of /bin/ld_static. According to AMD, | |
| 315 * the rex prefix must be last. | |
| 316 * | |
| 317 * For now, we will follow the convention of gcc, which places | |
| 318 * the LOCK byte in front of the REX byte. | |
| 319 */ | |
| 320 if (rex_index >= 0) { | |
| 321 if ((rex_index + 1) != inst_state->num_prefix_bytes) { | |
| 322 *is_legal = FALSE; | |
| 323 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClRexPrefixNotLast); | |
| 324 } | |
| 325 } | |
| 326 } | |
| 327 } | |
| 328 | |
| 329 /* Checks instruction details of the current instruction to see if there | |
| 330 * are any red flags that make the instruction illegal. | |
| 331 * | |
| 332 * Parameters are: | |
| 333 * state : The current validator state to check. | |
| 334 * is_legal: Flag set to FALSE if any prefix problems are found. | |
| 335 * disallows_flags : Set of flags, describing the reason(s) the | |
| 336 * current instruction in the validator state is not | |
| 337 * legal in native client. Updated as appropriate. | |
| 338 */ | |
| 339 static void NaClCheckIfMarkedIllegal(NaClValidatorState* state, | |
| 340 Bool* is_legal, | |
| 341 NaClDisallowsFlags* disallows_flags) { | |
| 342 if (NACL_IFLAG(NaClIllegal) & state->cur_inst->flags) { | |
| 343 *is_legal = FALSE; | |
| 344 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClMarkedIllegal); | |
| 345 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
| 346 NaClGetReasonWhyDisallowed(NaClMarkedIllegal))); | |
| 347 } | |
| 348 | |
| 349 /* Check other forms to disallow. | |
| 350 * TODO(karl): Move these checks into the model generator, setting the | |
| 351 * NaClIllegal flag. Once that is completed, this switch statement can | |
| 352 * can be removed. | |
| 353 */ | |
| 354 switch (state->cur_inst->insttype) { | |
| 355 case NACLi_RETURN: | |
| 356 case NACLi_EMMX: | |
| 357 /* EMMX needs to be supported someday but isn't ready yet. */ | |
| 358 case NACLi_ILLEGAL: | |
| 359 case NACLi_SYSTEM: | |
| 360 case NACLi_RDMSR: | |
| 361 case NACLi_RDTSCP: | |
| 362 case NACLi_LONGMODE: | |
| 363 case NACLi_SVM: | |
| 364 case NACLi_3BYTE: | |
| 365 case NACLi_UNDEFINED: | |
| 366 *is_legal = FALSE; | |
| 367 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClMarkedIllegal); | |
| 368 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
| 369 NaClGetReasonWhyDisallowed(NaClMarkedIllegal))); | |
| 370 break; | |
| 371 case NACLi_INVALID: | |
| 372 *is_legal = FALSE; | |
| 373 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClMarkedInvalid); | |
| 374 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
| 375 NaClGetReasonWhyDisallowed(NaClMarkedInvalid))); | |
| 376 break; | |
| 377 case NACLi_SYSCALL: | |
| 378 case NACLi_SYSENTER: | |
| 379 *is_legal = FALSE; | |
| 380 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClMarkedSystem); | |
| 381 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
| 382 NaClGetReasonWhyDisallowed(NaClMarkedSystem))); | |
| 383 break; | |
| 384 default: | |
| 385 break; | |
| 386 } | |
| 387 } | |
| 388 | |
| 389 /* Prints out error messages describing why the current instruction | |
| 390 * in the given validator state is not legal in native client. | |
| 391 * | |
| 392 * Parameters are: | |
| 393 * state : The current validator state to check. | |
| 394 * disallows_flags : Set of flags, describing the reason(s) the | |
| 395 * current instruction in the validator state is not | |
| 396 * legal in native client. Updated as appropriate. | |
| 397 */ | |
| 398 static void NaClReportWhyNaClIllegal(NaClValidatorState* state, | |
| 399 NaClDisallowsFlags disallows_flags) { | |
| 400 if (NACL_EMPTY_DISALLOWS_FLAGS != disallows_flags) { | |
| 401 int i; | |
| 402 Bool printed_reason = FALSE; | |
| 403 NaClInstState* inst_state = state->cur_inst_state; | |
| 404 /* Print out error message for each reason the instruction is disallowed. */ | |
| 405 for (i = 0; i < NaClDisallowsFlagEnumSize; ++i) { | |
| 406 if (disallows_flags & NACL_DISALLOWS_FLAG(i)) { | |
| 407 const char* why_disallowed = NaClReasonWhyDisallowed(i); | |
| 408 if (NULL != why_disallowed) { | |
| 409 printed_reason = TRUE; | |
| 410 NaClValidatorInstMessage( | |
| 411 LOG_ERROR, state, inst_state, "%s\n", why_disallowed); | |
| 412 } | |
| 413 } | |
| 414 /* Stop looking if we should quit reporting errors. */ | |
| 415 if (state->quit) break; | |
| 416 } | |
| 417 /* Be sure we print a reason (in case the switch isn't complete). */ | |
| 418 if (!printed_reason) { | |
| 419 disallows_flags = NACL_EMPTY_DISALLOWS_FLAGS; | |
| 420 } | |
| 421 } | |
| 422 if (NACL_EMPTY_DISALLOWS_FLAGS == disallows_flags) { | |
| 423 /* No known reason was recorded, but the instruction was recorded as illegal
. | |
| 424 * Report that the instruction is not acceptable. | |
| 425 */ | |
| 426 NaClValidatorInstMessage(LOG_ERROR, state, state->cur_inst_state, | |
| 427 "%s\n", kNaClGenericReasonDisallowed); | |
| 428 } | |
| 429 } | |
| 430 | |
| 431 void NaClValidateInstructionLegal(NaClValidatorState* state) { | |
| 432 Bool is_legal = TRUE; | |
| 433 NaClDisallowsFlags disallows_flags = NACL_EMPTY_DISALLOWS_FLAGS; | |
| 434 DEBUG_OR_ERASE({ | |
| 435 struct Gio* g = NaClLogGetGio(); | |
| 436 NaClLog(LOG_INFO, "->NaClValidateInstructionLegal\n"); | |
| 437 NaClInstPrint(g, state->decoder_tables, | |
| 438 NaClInstStateInst(state->cur_inst_state)); | |
| 439 NaClExpVectorPrint(g, state); | |
| 440 }); | |
| 441 NaClCheckForPrefixIssues(state, &is_legal, &disallows_flags); | |
| 442 NaClCheckIfMarkedIllegal(state, &is_legal, &disallows_flags); | |
| 443 if (!is_legal) { | |
| 444 NaClReportWhyNaClIllegal(state, disallows_flags); | |
| 445 } | |
| 446 DEBUG(NaClLog(LOG_INFO, | |
| 447 "<-NaClValidateInstructionLegal: is_legal = %"NACL_PRIdBool"\n", | |
| 448 is_legal)); | |
| 449 } | |
| OLD | NEW |