LCOV - code coverage report
Current view: directory - src/trusted/validator/x86/decoder - ncop_exps.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 357 316 88.5 %
Date: 2014-06-18 Functions: 0 0 -

       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                 : #include "native_client/src/trusted/validator/x86/decoder/ncop_exps.h"
       8                 : 
       9                 : #include <stdio.h>
      10                 : #include <ctype.h>
      11                 : #include <string.h>
      12                 : #include <assert.h>
      13                 : #include <sys/stat.h>
      14                 : 
      15                 : #include "native_client/src/include/portability.h"
      16                 : #include "native_client/src/shared/platform/nacl_log.h"
      17                 : #include "native_client/src/shared/utils/types.h"
      18                 : #include "native_client/src/trusted/validator/x86/decoder/gen/ncop_expr_node_flag_impl.h"
      19                 : #include "native_client/src/trusted/validator/x86/decoder/gen/ncop_expr_node_kind_impl.h"
      20                 : #include "native_client/src/trusted/validator/x86/decoder/nc_decode_tables_types.h"
      21                 : #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_internal.h"
      22                 : 
      23                 : /* To turn on debugging of instruction decoding, change value of
      24                 :  * DEBUGGING to 1.
      25                 :  *
      26                 :  * WARNING: Debugging messages inside of print messages must be sent to the
      27                 :  * same gio stream as being printed, since they may be used by another
      28                 :  * nacl log message that has locked the access to NaClLogGetGio().
      29                 :  */
      30                 : #define DEBUGGING 0
      31                 : 
      32                 : #include "native_client/src/shared/utils/debugging.h"
      33                 : 
      34                 : #include "native_client/src/trusted/validator/x86/decoder/ncopcode_desc_inl.c"
      35                 : #include "native_client/src/trusted/validator/x86/decoder/ncop_exps_inl.c"
      36                 : 
      37            2962 : void NaClPrintExpFlags(struct Gio* file, NaClExpFlags flags) {
      38            2962 :   if (flags == 0) {
      39             212 :     gprintf(file, "0");
      40             212 :   } else {
      41            2750 :     NaClExpFlag f;
      42            2750 :     Bool is_first = TRUE;
      43           93500 :     for (f = 0; f < NaClExpFlagEnumSize; f++) {
      44           44000 :       if (flags & NACL_EFLAG(f)) {
      45            5513 :         if (is_first) {
      46            2750 :           is_first = FALSE;
      47            2750 :         } else {
      48            2763 :           gprintf(file, " | ");
      49                 :         }
      50            5513 :         gprintf(file, "%s", NaClExpFlagName(f));
      51            5513 :       }
      52           44000 :     }
      53                 :   }
      54            2962 : }
      55                 : 
      56                 : typedef struct NaClExpKindDescriptor {
      57                 :   /* The name of the expression operator. */
      58                 :   NaClExpKind name;
      59                 :   /* The rank (i.e. number of children) the expression operator has. */
      60                 :   const int rank;
      61                 : } NaClExpKindDescriptor;
      62                 : 
      63                 : /* The print names of valid NaClExpKind values. */
      64                 : static const NaClExpKindDescriptor
      65                 : g_NaClExpKindDesc[NaClExpKindEnumSize + 1]= {
      66                 :   {UndefinedExp, 0},
      67                 :   {ExprRegister, 0},
      68                 :   {OperandReference, 1},
      69                 :   {ExprConstant, 0},
      70                 :   {ExprSegmentAddress, 2},
      71                 :   {ExprMemOffset, 4},
      72                 :   {ExprNaClIllegal, 0},
      73                 : };
      74                 : 
      75           26588 : int NaClExpKindRank(NaClExpKind kind) {
      76           53176 :   assert(kind == g_NaClExpKindDesc[kind].name);
      77           26588 :   return g_NaClExpKindDesc[kind].rank;
      78                 : }
      79                 : 
      80                 : /* Returns the register defined by the given node. */
      81               0 : NaClOpKind NaClGetExpRegister(NaClExp* node) {
      82               0 :   return NaClGetExpRegisterInline(node);
      83                 : }
      84                 : 
      85                 : /* Returns the name of the register defined by the indexed node in the
      86                 :  * vector of nodes.
      87                 :  */
      88            3110 : NaClOpKind NaClGetExpVectorRegister(NaClExpVector* vector,
      89            3110 :                                     int node) {
      90            3110 :   return NaClGetExpRegisterInline(&vector->node[node]);
      91                 : }
      92                 : 
      93                 : static int NaClPrintDisassembledExp(struct Gio* file,
      94                 :                                     NaClInstState* state,
      95                 :                                     uint32_t index);
      96                 : 
      97                 : /* Print the characters in the given string using lower case. */
      98            4522 : static void NaClPrintLower(struct Gio* file, char* str) {
      99           32084 :   while (*str) {
     100           23040 :     gprintf(file, "%c", tolower(*str));
     101           23040 :     ++str;
     102           23040 :   }
     103            4522 : }
     104                 : 
     105                 : /* Print out the given constant expression node to the given file. */
     106                 : static void NaClPrintDisassembledConst(
     107            1361 :     struct Gio* file, NaClInstState* state, NaClExp* node) {
     108            2722 :   assert(node->kind == ExprConstant);
     109            1361 :   if (node->flags & NACL_EFLAG(ExprJumpTarget)) {
     110             210 :     NaClPcAddress target = NaClInstStatePrintableAddress(state)
     111             210 :         + state->bytes.length + (NaClPcNumber) NaClGetExprSignedValue(node);
     112             210 :     gprintf(file, "0x%"NACL_PRIxNaClPcAddress, target);
     113            1361 :   }else if (node->flags & NACL_EFLAG(ExprUnsignedHex)) {
     114             443 :     gprintf(file, "0x%"NACL_PRIx64, NaClGetExprUnsignedValue(node));
     115            1151 :   } else if (node->flags & NACL_EFLAG(ExprSignedHex)) {
     116             401 :     int64_t val = NaClGetExprSignedValue(node);
     117             401 :     if (val < 0) {
     118              57 :       val = -val;
     119              57 :       gprintf(file, "-0x%"NACL_PRIx64, val);
     120              57 :     } else {
     121             344 :       gprintf(file, "0x%"NACL_PRIx64, val);
     122                 :     }
     123             708 :   } else if (node->flags & NACL_EFLAG(ExprUnsignedInt)) {
     124               0 :     gprintf(file, "%"NACL_PRIu64, NaClGetExprUnsignedValue(node));
     125               0 :   } else {
     126                 :     /* Assume ExprSignedInt. */
     127             307 :     gprintf(file, "%"NACL_PRId64, NaClGetExprSignedValue(node));
     128                 :   }
     129            1361 : }
     130                 : 
     131                 : #define NACLOP_REG_PREFIX "Reg"
     132                 : 
     133            6280 : size_t NaClOpRegName(NaClOpKind reg, char* buffer, size_t buffer_size) {
     134            6280 :   const char* name = NaClOpKindName(reg);
     135            6280 :   char* str;
     136            6280 :   size_t index;
     137                 : 
     138                 :   /* Fail if no room to put register name. */
     139            6280 :   if (buffer_size == 0) return 0;
     140            6280 :   buffer[0] = '\0';  /* To be safe, in case we exit prematurely. */
     141                 : 
     142                 :   /* Get name for register. */
     143            6280 :   name = NaClOpKindName(reg);
     144            6280 :   if (NULL == name) return 0;
     145                 : 
     146                 :   /* Strip off 'Reg' prefix from register name, if it exists. */
     147            6280 :   str = strstr(name, NACLOP_REG_PREFIX);
     148            6280 :   if (str != name) return 0;
     149            6280 :   str += strlen(NACLOP_REG_PREFIX);
     150                 : 
     151                 :   /* Copy the name, converting characters to lower case. */
     152           51310 :   for (index = 0; (index + 1) < buffer_size; ++index) {
     153           25655 :     char ch = tolower(str[index]);
     154           31935 :     if ('\0' == ch) break;
     155           19375 :     buffer[index] = tolower(str[index]);
     156           19375 :   }
     157                 : 
     158                 :   /* Be sure to add null character at end. */
     159            6280 :   buffer[index] = '\0';
     160            6280 :   return index;
     161            6280 : }
     162                 : 
     163                 : #define MAX_REGISTER_SIZE 256
     164                 : 
     165                 : /* Print out the disassembled representation of the given register
     166                 :  * to the given file.
     167                 :  */
     168            6280 : static void NaClPrintDisassembledRegKind(struct Gio* file, NaClOpKind reg) {
     169            6280 :   char buffer[MAX_REGISTER_SIZE];
     170            6280 :   NaClOpRegName(reg, buffer, MAX_REGISTER_SIZE);
     171            6280 :   gprintf(file, "%c%s", '%', buffer);
     172            6280 : }
     173                 : 
     174            4898 : static INLINE void NaClPrintDisassembledReg(struct Gio* file, NaClExp* node) {
     175            4898 :   NaClPrintDisassembledRegKind(file, NaClGetExpRegisterInline(node));
     176            4898 : }
     177                 : 
     178             610 : void NaClExpVectorPrint(struct Gio* file, NaClInstState* state) {
     179             610 :   uint32_t i;
     180             610 :   NaClExpVector* vector = NaClInstStateExpVector(state);
     181             610 :   gprintf(file, "NaClExpVector[%d] = {\n", vector->number_expr_nodes);
     182            7144 :   for (i = 0; i < vector->number_expr_nodes; i++) {
     183            2962 :     NaClExp* node = &vector->node[i];
     184            5924 :     gprintf(file, "  { %s[%d] , ",
     185            2962 :             NaClExpKindName(node->kind),
     186            2962 :             NaClExpKindRank(node->kind));
     187            2962 :     switch (node->kind) {
     188                 :       case ExprRegister:
     189            1177 :         NaClPrintDisassembledReg(file, node);
     190            1177 :         break;
     191                 :       case ExprConstant:
     192             519 :         NaClPrintDisassembledConst(file, state, node);
     193             519 :         break;
     194                 :       default:
     195            1266 :         gprintf(file, "%"NACL_PRIu64, NaClGetExprUnsignedValue(node));
     196            1266 :         break;
     197                 :     }
     198            2962 :     gprintf(file, ", ");
     199            2962 :     NaClPrintExpFlags(file, node->flags);
     200            2962 :     gprintf(file, " },\n");
     201            2962 :   }
     202             610 :   gprintf(file, "};\n");
     203             610 : }
     204                 : 
     205                 : /* Print out the given (memory offset) expression node to the given file.
     206                 :  * Returns the index of the node following the given (indexed) memory offset.
     207                 :  */
     208            1113 : static int NaClPrintDisassembledMemOffset(struct Gio* file,
     209            1113 :                                       NaClInstState *state,
     210            1113 :                                       int index) {
     211            1113 :   NaClExpVector* vector = NaClInstStateExpVector(state);
     212            1113 :   int r1_index = index + 1;
     213            1113 :   int r2_index = r1_index + NaClExpWidth(vector, r1_index);
     214            1113 :   int scale_index = r2_index + NaClExpWidth(vector, r2_index);
     215            1113 :   int disp_index = scale_index + NaClExpWidth(vector, scale_index);
     216            1113 :   NaClOpKind r1 = NaClGetExpVectorRegister(vector, r1_index);
     217            1113 :   NaClOpKind r2 = NaClGetExpVectorRegister(vector, r2_index);
     218            1113 :   uint64_t scale = NaClGetExprUnsignedValue(&vector->node[scale_index]);
     219            1113 :   int64_t disp = NaClGetExprSignedValue(&vector->node[disp_index]);
     220            2226 :   assert(ExprMemOffset == vector->node[index].kind);
     221            1113 :   gprintf(file,"[");
     222            1113 :   if (r1 != RegUnknown) {
     223            1045 :     NaClPrintDisassembledRegKind(file, r1);
     224            1045 :   }
     225            1113 :   if (r2 != RegUnknown) {
     226             337 :     if (r1 != RegUnknown) {
     227             329 :       gprintf(file, "+");
     228             329 :     }
     229             337 :     NaClPrintDisassembledRegKind(file, r2);
     230             337 :     gprintf(file, "*%d", (uint32_t) scale);
     231             337 :   }
     232            1113 :   if (disp != 0) {
     233             369 :     if ((r1 != RegUnknown || r2 != RegUnknown) &&
     234             257 :         !NaClIsExpNegativeConstant(vector, disp_index)) {
     235             219 :       gprintf(file, "+");
     236             219 :     }
     237                 :     /* Recurse to handle print using format flags. */
     238             309 :     NaClPrintDisassembledExp(file, state, disp_index);
     239            1121 :   } else if (r1 == RegUnknown && r2 == RegUnknown) {
     240                 :     /* be sure to generate case: [0x0]. */
     241               8 :     NaClPrintDisassembledExp(file, state, disp_index);
     242               8 :   }
     243            1113 :   gprintf(file, "]");
     244            1113 :   return disp_index + NaClExpWidth(vector, disp_index);
     245                 : }
     246                 : 
     247                 : /* Retrurns true if the segment register of the indexed segment address is DS,
     248                 :  * and DS has been marked (by the instruction) as the default register
     249                 :  * for the segment address.
     250                 :  */
     251             439 : static Bool IsSegmentAddressDsRegPair(NaClInstState* state,
     252             439 :                                       int index) {
     253             439 :   NaClExpVector* vector = NaClInstStateExpVector(state);
     254             439 :   NaClExp* segment_address = &vector->node[index];
     255             439 :   NaClExp* segment_register =
     256             439 :       &vector->node[NaClGetExpKidIndex(vector, index, 0)];
     257             553 :   return NaClHasBit(segment_address->flags, NACL_EFLAG(ExprDSrCase)) &&
     258                 :       (segment_register->kind == ExprRegister) &&
     259             114 :       (RegDS == NaClGetExpRegisterInline(segment_register));
     260             439 : }
     261                 : 
     262                 : /* Retrurns true if the segment register of the index segment address is ES,
     263                 :  * and ES has been marked (by the instruction) as the default register
     264                 :  * for the segment address.
     265                 :  */
     266             325 : static Bool IsSegmentAddressEsRegPair(NaClInstState* state,
     267             325 :                                       int index) {
     268             325 :   NaClExpVector* vector = NaClInstStateExpVector(state);
     269             325 :   NaClExp* segment_address = &vector->node[index];
     270             325 :   NaClExp* segment_register =
     271             325 :       &vector->node[NaClGetExpKidIndex(vector, index, 0)];
     272             583 :   return NaClHasBit(segment_address->flags, NACL_EFLAG(ExprESrCase)) &&
     273                 :       (segment_register->kind == ExprRegister) &&
     274             258 :       (RegES == NaClGetExpRegisterInline(segment_register));
     275             325 : }
     276                 : 
     277                 : /* Print out the given (segment address) expression node to the
     278                 :  * given file. Returns the index of the node following the
     279                 :  * given (indexed) segment address.
     280                 :  */
     281             439 : static int NaClPrintDisassembledSegmentAddr(struct Gio* file,
     282             439 :                                             NaClInstState* state,
     283             439 :                                             int index) {
     284             439 :   int memory_address;
     285             439 :   NaClExpVector* vector = NaClInstStateExpVector(state);
     286                 :   /* If segment register is default. If so, do not print. */
     287             439 :   if (IsSegmentAddressDsRegPair(state, index) ||
     288             325 :       IsSegmentAddressEsRegPair(state, index)) {
     289                 :     /* Segment register matches default.  Don't print. */
     290             372 :   } else {
     291                 :     /* Print the segment register associated with the segment address. */
     292              67 :     NaClPrintDisassembledExp(file, state, index + 1);
     293              67 :     gprintf(file, ":");
     294                 :   }
     295             439 :   memory_address = NaClGetExpKidIndex(vector, index, 1);
     296             439 :   if (vector->node[memory_address].kind == ExprRegister) {
     297                 :     /* Special case segment address, where the register corresponds to
     298                 :      * a memory address. Print out the register in '[]' brackets to
     299                 :      * communicate that it is a memory reference.
     300                 :      */
     301             372 :     int result;
     302             372 :     gprintf(file, "[");
     303             372 :     result = NaClPrintDisassembledExp(file, state, memory_address);
     304             372 :     gprintf(file, "]");
     305             372 :     return result;
     306                 :   } else {
     307                 :     /* print out memory address associated with segment address. */
     308              67 :     return NaClPrintDisassembledExp(file, state, memory_address);
     309                 :   }
     310             439 : }
     311                 : 
     312                 : /* Print out the given expression node to the given file.
     313                 :  * Returns the index of the node following the given indexed
     314                 :  * expression.
     315                 :  */
     316           11405 : static int NaClPrintDisassembledExp(struct Gio* file,
     317           11405 :                                     NaClInstState* state,
     318           11405 :                                     uint32_t index) {
     319           11405 :   NaClExp* node;
     320           11405 :   NaClExpVector* vector = NaClInstStateExpVector(state);
     321           22810 :   assert(index < vector->number_expr_nodes);
     322           11405 :   node = &vector->node[index];
     323           11405 :   switch (node->kind) {
     324                 :     default:
     325               0 :       gprintf(file, "undefined");
     326               0 :       return index + 1;
     327                 :     case ExprRegister:
     328            3721 :       NaClPrintDisassembledReg(file, node);
     329            3721 :       return index + 1;
     330                 :     case OperandReference:
     331            5290 :       return NaClPrintDisassembledExp(file, state, index + 1);
     332                 :     case ExprConstant:
     333             842 :       NaClPrintDisassembledConst(file, state, node);
     334             842 :       return index + 1;
     335                 :     case ExprSegmentAddress:
     336             439 :       return NaClPrintDisassembledSegmentAddr(file, state, index);
     337                 :     case ExprMemOffset:
     338            1113 :       return NaClPrintDisassembledMemOffset(file, state, index);
     339                 :     case ExprNaClIllegal:
     340               0 :       gprintf(file, "*NaClIllegal*");
     341               0 :       return index + 1;
     342                 :   }
     343           11405 : }
     344                 : 
     345                 : /* Returns true if there is a segment override in the segment address
     346                 :  * node defined by vector[seg_addr_index].
     347                 :  *
     348                 :  * Parameters:
     349                 :  *   vector - The node expression tree associated with the instruction.
     350                 :  *   seg_addr_index - The index to the segment address node to check.
     351                 :  *   seg_eflag - The expr flag that must be associated with the
     352                 :  *      segment address node to be considered for an override.
     353                 :  *   seg_reg - The expected (i.e. default) segment register
     354                 :  *      to be associated with the segment address.
     355                 :  */
     356             102 : static Bool NaClHasSegmentOverride(NaClExpVector* vector,
     357             102 :                                    int seg_addr_index,
     358             102 :                                    NaClExpFlag seg_eflag,
     359             102 :                                    NaClOpKind seg_reg) {
     360             102 :   NaClExp* seg_node = &vector->node[seg_addr_index];
     361             102 :   if (seg_node->flags & NACL_EFLAG(seg_eflag)) {
     362              52 :     int seg_index = seg_addr_index + 1;
     363              52 :     NaClExp* node = &vector->node[seg_index];
     364             104 :     if ((ExprRegister == node->kind) &&
     365              52 :         (seg_reg != NaClGetExpRegisterInline(node))) {
     366               2 :       return TRUE;
     367                 :     }
     368              50 :   }
     369             100 :   return FALSE;
     370             102 : }
     371                 : 
     372                 : /* Prints out the segment register associated with the segment
     373                 :  * address node defined by vector[seg_addr_index].
     374                 :  *
     375                 :  * Parameters:
     376                 :  *    file - The Gio file to print the segment register to.
     377                 :  *    is_first - True if the first operand of the instruction.
     378                 :  *    vector - The node expression tree associated with the instruction.
     379                 :  *   seg_addr_index - The index to the segment address node to check.
     380                 :  */
     381               2 : static void NaClPrintSegmentOverride(struct Gio* file,
     382               2 :                                      Bool* is_first,
     383               2 :                                      NaClInstState* state,
     384               2 :                                      NaClExpVector* vector,
     385               2 :                                      int seg_addr_index) {
     386               2 :   int seg_index = seg_addr_index + 1;
     387               2 :   if (*is_first) {
     388               2 :     gprintf(file, " ");
     389               2 :     *is_first = FALSE;
     390               2 :   } else {
     391               0 :     gprintf(file, ", ");
     392                 :   }
     393               2 :   NaClPrintDisassembledExp(file, state, seg_index);
     394               2 : }
     395                 : 
     396                 : /* Print the flag name if the flag is defined for the corresponding operand.
     397                 :  * Used to print out set/use/zero extend information for partial instructions.
     398                 :  */
     399            3342 : static void NaClPrintAddOperandFlag(struct Gio* f,
     400            3342 :                                     const NaClOp* op,
     401            3342 :                                     NaClOpFlag flag,
     402            3342 :                                     const char* flag_name) {
     403            3342 :   if (op->flags & NACL_OPFLAG(flag)) {
     404            1468 :     gprintf(f, "%s", flag_name);
     405            1468 :   }
     406            3342 : }
     407                 : 
     408                 : /* Print the given instruction opcode of the give state, to the
     409                 :  * given file.
     410                 :  */
     411            4522 : static void NaClPrintDisassembled(struct Gio* file,
     412            4522 :                                   NaClInstState* state,
     413            4522 :                                   const NaClInst* inst) {
     414            4522 :   uint32_t tree_index = 0;
     415            4522 :   Bool is_first = TRUE;
     416            4522 :   Bool not_printed_prefix_segment = TRUE;
     417            4522 :   NaClExp* node;
     418            4522 :   NaClExpVector* vector = NaClInstStateExpVector(state);
     419                 : 
     420                 :   /* Print the name of the instruction. */
     421            4522 :   if (NaClHasBit(inst->flags, NACL_IFLAG(PartialInstruction))) {
     422                 :     /* Instruction has been simplified. Print out corresponding
     423                 :      * hints to the reader, so that they know that the instruction
     424                 :      * has been simplified.
     425                 :      */
     426            1294 :     gprintf(file, "[P] ");
     427            1294 :     NaClPrintLower(file, (char*) NaClMnemonicName(inst->name));
     428            1294 :     if (NaClHasBit(inst->flags, NACL_IFLAG(NaClIllegal))) {
     429             133 :       gprintf(file, "(illegal)");
     430             133 :     }
     431            1294 :   } else {
     432            3228 :     NaClPrintLower(file, (char*) NaClMnemonicName(inst->name));
     433                 :   }
     434                 : 
     435                 :   /* Use the generated expression tree to print out (non-implicit) operands
     436                 :    * of the instruction.
     437                 :    */
     438           15118 :   while (tree_index < vector->number_expr_nodes) {
     439            6074 :     node = &vector->node[tree_index];
     440           12148 :     if (node->kind != OperandReference ||
     441                 :         (NACL_EMPTY_EFLAGS == (node->flags & NACL_EFLAG(ExprImplicit)))) {
     442            5290 :       if (is_first) {
     443            2948 :         gprintf(file, " ");
     444            2948 :         is_first = FALSE;
     445            2948 :       } else {
     446            2342 :         gprintf(file, ", ");
     447                 :       }
     448            5290 :       NaClPrintDisassembledExp(file, state, tree_index);
     449                 : 
     450                 :       /* If this is a partial instruction, add set/use information
     451                 :        * so that that it is more clear what was matched.
     452                 :        */
     453            6409 :       if (NaClHasBit(inst->flags, NACL_IFLAG(PartialInstruction)) &&
     454                 :           node->kind == OperandReference) {
     455            1119 :         const NaClOp* op =
     456            2238 :             NaClGetInstOperandInline(state->decoder_tables,
     457                 :                                      inst,
     458            1119 :                                      (uint8_t) NaClGetExprUnsignedValue(node));
     459            1119 :         if (NaClHasBit(op->flags, (NACL_OPFLAG(OpSet) |
     460                 :                                    NACL_OPFLAG(OpUse) |
     461                 :                                    NACL_OPFLAG(OperandZeroExtends_v)))) {
     462            1114 :           gprintf(file, " (");
     463            1114 :           NaClPrintAddOperandFlag(file, op, OpSet, "s");
     464            1114 :           NaClPrintAddOperandFlag(file, op, OpUse, "u");
     465            1114 :           NaClPrintAddOperandFlag(file, op, OperandZeroExtends_v, "z");
     466            1114 :           gprintf(file, ")");
     467            1114 :         }
     468            1119 :       }
     469            7642 :     } else if (not_printed_prefix_segment &&
     470                 :                (OperandReference == node->kind) &&
     471                 :                (node->flags & NACL_EFLAG(ExprImplicit))) {
     472                 :       /* Print out segment override of implicit segment address, if
     473                 :        * applicable.
     474                 :        */
     475             784 :       if (OperandReference == node->kind) {
     476             784 :         int seg_addr_index = tree_index + 1;
     477             784 :         if (ExprSegmentAddress == vector->node[seg_addr_index].kind) {
     478              52 :           if (NaClHasSegmentOverride(vector, seg_addr_index,
     479                 :                                      ExprDSrCase, RegDS)) {
     480               2 :             NaClPrintSegmentOverride(file, &is_first, state, vector,
     481                 :                                      seg_addr_index);
     482              52 :           } else if (NaClHasSegmentOverride(vector, seg_addr_index,
     483                 :                                             ExprESrCase, RegES)) {
     484               0 :             NaClPrintSegmentOverride(file, &is_first, state, vector,
     485                 :                                      seg_addr_index);
     486               0 :           }
     487              52 :         }
     488             784 :       }
     489             784 :     }
     490                 :     /* Skip over expression to next expresssion. */
     491            6074 :     tree_index += NaClExpWidth(vector, tree_index);
     492            6074 :   }
     493            4522 : }
     494                 : 
     495            4522 : void NaClInstStateInstPrint(struct Gio* file, NaClInstState* state) {
     496            4522 :   int i;
     497            4522 :   const NaClInst* inst;
     498                 : 
     499                 :   /* Print out the address and the inst bytes. */
     500            4522 :   int length = NaClInstStateLength(state);
     501                 : 
     502                 :   DEBUG_OR_ERASE(
     503                 :       NaClInstPrint(file, state->decoder_tables, NaClInstStateInst(state)));
     504            9044 :   DEBUG(NaClExpVectorPrint(file, state));
     505            9044 :   gprintf(file, "%"NACL_PRIxNaClPcAddressAll": ",
     506            4522 :           NaClInstStatePrintableAddress(state));
     507           37858 :   for (i = 0; i < length; ++i) {
     508           14407 :     gprintf(file, "%02"NACL_PRIx8" ", NaClInstStateByte(state, i));
     509           14407 :   }
     510          115890 :   for (i = length; i < NACL_MAX_BYTES_PER_X86_INSTRUCTION; ++i) {
     511           53423 :     gprintf(file, "   ");
     512           53423 :   }
     513                 : 
     514                 :   /* Print out the assembly instruction it disassembles to. */
     515            4522 :   inst = NaClInstStateInst(state);
     516            4522 :   NaClPrintDisassembled(file, state, inst);
     517            4522 :   gprintf(file, "\n");
     518            4522 : }
     519                 : 
     520                 : /* Defines a buffer size big enough to hold an instruction. */
     521                 : #define MAX_INST_TEXT_SIZE 256
     522                 : 
     523               0 : char* NaClInstStateInstructionToString(struct NaClInstState* state) {
     524                 :   /* Print to a memory buffer, and then duplicate. */
     525               0 :   struct GioMemoryFile filemem;
     526               0 :   struct Gio *file = (struct Gio*) &filemem;
     527               0 :   char buffer[MAX_INST_TEXT_SIZE];
     528               0 :   char* result;
     529                 : 
     530                 :   /* Note: Be sure to leave an extra byte to add the null character to
     531                 :    * the end of the string.
     532                 :    */
     533               0 :   GioMemoryFileCtor(&filemem, buffer, MAX_INST_TEXT_SIZE - 1);
     534               0 :   NaClInstStateInstPrint(file, state);
     535               0 :   buffer[filemem.curpos < MAX_INST_TEXT_SIZE
     536                 :          ? filemem.curpos : MAX_INST_TEXT_SIZE] ='\0';
     537               0 :   result = strdup(buffer);
     538               0 :   GioMemoryFileDtor(file);
     539               0 :   return result;
     540                 : }
     541                 : 
     542           23626 : int NaClExpWidth(NaClExpVector* vector, int node) {
     543           23626 :   int i;
     544           23626 :   int count = 1;
     545           23626 :   int num_kids = NaClExpKindRank(vector->node[node].kind);
     546           70268 :   for (i = 0; i < num_kids; i++) {
     547           11508 :     count += NaClExpWidth(vector, node + count);
     548           11508 :   }
     549           23626 :   return count;
     550                 : }
     551                 : 
     552            1648 : int NaClGetExpKidIndex(NaClExpVector* vector, int node, int kid) {
     553            1648 :   node++;
     554            3884 :   while (kid-- > 0) {
     555             588 :     node += NaClExpWidth(vector, node);
     556             588 :   }
     557            1648 :   return node;
     558                 : }
     559                 : 
     560               0 : int NaClGetExpParentIndex(NaClExpVector* vector, int index) {
     561               0 :   int node_rank;
     562               0 :   int num_kids = 1;
     563               0 :   while (index > 0) {
     564               0 :     --index;
     565               0 :     node_rank = NaClExpKindRank(vector->node[index].kind);
     566               0 :     if (node_rank >= num_kids) {
     567               0 :       return index;
     568                 :     } else {
     569               0 :       num_kids -= (node_rank - 1);
     570                 :     }
     571               0 :   }
     572               0 :   return -1;
     573               0 : }
     574                 : 
     575             138 : int NaClGetNthExpKind(NaClExpVector* vector,
     576             138 :                       NaClExpKind kind,
     577             138 :                       int n) {
     578             138 :   if (n > 0) {
     579             138 :     uint32_t i;
     580             828 :     for (i = 0; i < vector->number_expr_nodes; ++i) {
     581             414 :       if (kind == vector->node[i].kind) {
     582             276 :         --n;
     583             414 :         if (n == 0) return i;
     584             138 :       }
     585             276 :     }
     586               0 :   }
     587               0 :   return -1;
     588             138 : }
     589                 : 
     590             257 : Bool NaClIsExpNegativeConstant(NaClExpVector* vector, int index) {
     591             257 :   NaClExp* node = &vector->node[index];
     592             257 :   switch (node->kind) {
     593                 :     case ExprConstant:
     594             514 :       if (node->flags & NACL_EFLAG(ExprUnsignedHex) ||
     595                 :           node->flags & NACL_EFLAG(ExprUnsignedInt)) {
     596               0 :         return FALSE;
     597                 :       } else {
     598                 :         /* Assume signed value. */
     599             257 :         return NaClGetExprSignedValue(node) < 0;
     600                 :       }
     601                 :       break;
     602                 :     default:
     603               0 :       break;
     604                 :   }
     605               0 :   return FALSE;
     606             257 : }
     607                 : 
     608                 : /* Dummy routine to allow unreferenced NaClGetInstNumberOperandsInline
     609                 :  * inline.
     610                 :  */
     611               0 : uint8_t NaClNcopExpsDummyNaClGetInstNumberOperands(const NaClInst* inst) {
     612               0 :   return NaClGetInstNumberOperandsInline(inst);
     613                 : }

Generated by: LCOV version 1.7