ReadWriteRegisterFragment.h

Go to the documentation of this file.
00001 /* Generic code to be inserted into policy classes that are similar to VirtualMachineSemantics in how they organized the
00002  * registers in their State classes.   This header should not be protected with #ifdef because we might need to include it more
00003  * than once, each time into a different class.
00004  *
00005  * Most policies define a type named "ValueType", but some call it something else.  It is safe to #define ValueType to some
00006  * other type name.
00007  *
00008  * The policy state is assumed to be in the Policy::cur_state data member, which has arrays "gpr", "segreg" and "flag" whose
00009  * size are indicated by State class constants "n_gprs", "n_segregs", and "n_flags".
00010  *
00011  * Most policies store the "EIP" register in the cur_state along with the other registers.   However, at least one policy
00012  * stores it in the Policy object rather than the state.  Therefore, EIP_LOCATION should be a CPP symbol defining the location,
00013  * and defaults to "cur_state.ip".
00014  *
00015  * Some of the signExtend() and unsignedExtend() calls are only executed in the no-op case and are present only for their static
00016  * type. */
00017 
00018 #ifndef EIP_LOCATION
00019 #define EIP_LOCATION cur_state.ip
00020 #endif
00021 
00023 const RegisterDescriptor& findRegister(const std::string &regname, size_t nbits=0) {
00024     const RegisterDescriptor *reg = get_register_dictionary()->lookup(regname);
00025     if (!reg) {
00026         std::ostringstream ss;
00027         ss <<"Invalid register: \"" <<regname <<"\"";
00028         throw Exception(ss.str());
00029     }
00030     if (nbits>0 && reg->get_nbits()!=nbits) {
00031         std::ostringstream ss;
00032         ss <<"Invalid " <<nbits <<"-bit register: \"" <<regname <<"\" is "
00033            <<reg->get_nbits() <<" " <<(1==reg->get_nbits()?"byte":"bytes");
00034         throw Exception(ss.str());
00035     }
00036     return *reg;
00037 }
00038 
00040 template<size_t Len/*bits*/>
00041 ValueType<Len> readRegister(const char *regname) {
00042     return readRegister<Len>(findRegister(regname, Len));
00043 }
00044 
00046 template<size_t Len/*bits*/>
00047 void writeRegister(const char *regname, const ValueType<Len> &value) {
00048     writeRegister<Len>(findRegister(regname, Len), value);
00049 }
00050 
00052 template<size_t Len>
00053 ValueType<Len> readRegister(const RegisterDescriptor &reg) {
00054     switch (Len) {
00055         case 1:
00056             // Only FLAGS/EFLAGS bits have a size of one.  Other registers cannot be accessed at this granularity.
00057             if (reg.get_major()!=x86_regclass_flags)
00058                 throw Exception("bit access only valid for FLAGS/EFLAGS register");
00059             if (reg.get_minor()!=0 || reg.get_offset()>=cur_state.n_flags)
00060                 throw Exception("register not implemented in semantic policy");
00061             if (reg.get_nbits()!=1)
00062                 throw Exception("semantic policy supports only single-bit flags");
00063             return unsignedExtend<1, Len>(cur_state.flag[reg.get_offset()]);
00064 
00065         case 8:
00066             // Only general-purpose registers can be accessed at a byte granularity, and we can access only the low-order
00067             // byte or the next higher byte.  For instance, "al" and "ah" registers.
00068             if (reg.get_major()!=x86_regclass_gpr)
00069                 throw Exception("byte access only valid for general purpose registers");
00070             if (reg.get_minor()>=cur_state.n_gprs)
00071                 throw Exception("register not implemented in semantic policy");
00072             assert(reg.get_nbits()==8); // we had better be asking for a one-byte register (e.g., "ah", not "ax")
00073             switch (reg.get_offset()) {
00074                 case 0:
00075                     return extract<0, Len>(cur_state.gpr[reg.get_minor()]);
00076                 case 8:
00077                     return extract<8, 8+Len>(cur_state.gpr[reg.get_minor()]);
00078                 default:
00079                     throw Exception("invalid one-byte access offset");
00080             }
00081 
00082         case 16:
00083             if (reg.get_nbits()!=16)
00084                 throw Exception("invalid 2-byte register");
00085             if (reg.get_offset()!=0)
00086                 throw Exception("policy does not support non-zero offsets for word granularity register access");
00087             switch (reg.get_major()) {
00088                 case x86_regclass_segment:
00089                     if (reg.get_minor()>=cur_state.n_segregs)
00090                         throw Exception("register not implemented in semantic policy");
00091                     return unsignedExtend<16, Len>(cur_state.segreg[reg.get_minor()]);
00092                 case x86_regclass_gpr:
00093                     if (reg.get_minor()>=cur_state.n_gprs)
00094                         throw Exception("register not implemented in semantic policy");
00095                     return extract<0, Len>(cur_state.gpr[reg.get_minor()]);
00096                 case x86_regclass_flags:
00097                     if (reg.get_minor()!=0 || cur_state.n_flags<16)
00098                         throw Exception("register not implemented in semantic policy");
00099                     return unsignedExtend<16, Len>(concat(cur_state.flag[0],
00100                                                    concat(cur_state.flag[1],
00101                                                    concat(cur_state.flag[2],
00102                                                    concat(cur_state.flag[3],
00103                                                    concat(cur_state.flag[4],
00104                                                    concat(cur_state.flag[5],
00105                                                    concat(cur_state.flag[6],
00106                                                    concat(cur_state.flag[7],
00107                                                    concat(cur_state.flag[8],
00108                                                    concat(cur_state.flag[9],
00109                                                    concat(cur_state.flag[10],
00110                                                    concat(cur_state.flag[11],
00111                                                    concat(cur_state.flag[12],
00112                                                    concat(cur_state.flag[13],
00113                                                    concat(cur_state.flag[14],
00114                                                           cur_state.flag[15]))))))))))))))));
00115                 default:
00116                     throw Exception("word access not valid for this register type");
00117             }
00118 
00119         case 32:
00120             if (reg.get_offset()!=0)
00121                 throw Exception("policy does not support non-zero offsets for double word granularity register access");
00122             switch (reg.get_major()) {
00123                 case x86_regclass_gpr:
00124                     if (reg.get_minor()>=cur_state.n_gprs)
00125                         throw Exception("register not implemented in semantic policy");
00126                     return unsignedExtend<32, Len>(cur_state.gpr[reg.get_minor()]);
00127                 case x86_regclass_ip:
00128                     if (reg.get_minor()!=0)
00129                         throw Exception("register not implemented in semantic policy");
00130                     return unsignedExtend<32, Len>(EIP_LOCATION);
00131                 case x86_regclass_segment:
00132                     if (reg.get_minor()>=cur_state.n_segregs || reg.get_nbits()!=16)
00133                         throw Exception("register not implemented in semantic policy");
00134                     return unsignedExtend<16, Len>(cur_state.segreg[reg.get_minor()]);
00135                 case x86_regclass_flags: {
00136                     if (reg.get_minor()!=0 || cur_state.n_flags<32)
00137                         throw Exception("register not implemented in semantic policy");
00138                     if (reg.get_nbits()!=32)
00139                         throw Exception("register is not 32 bits");
00140                     return unsignedExtend<32, Len>(concat(readRegister<16>("flags"), // no-op sign extension
00141                                                    concat(cur_state.flag[16],
00142                                                    concat(cur_state.flag[17],
00143                                                    concat(cur_state.flag[18],
00144                                                    concat(cur_state.flag[19],
00145                                                    concat(cur_state.flag[20],
00146                                                    concat(cur_state.flag[21],
00147                                                    concat(cur_state.flag[22],
00148                                                    concat(cur_state.flag[23],
00149                                                    concat(cur_state.flag[24],
00150                                                    concat(cur_state.flag[25],
00151                                                    concat(cur_state.flag[26],
00152                                                    concat(cur_state.flag[27],
00153                                                    concat(cur_state.flag[28],
00154                                                    concat(cur_state.flag[29],
00155                                                    concat(cur_state.flag[30],
00156                                                           cur_state.flag[31])))))))))))))))));
00157                 }
00158                 default:
00159                     throw Exception("double word access not valid for this register type");
00160             }
00161 
00162         default:
00163             throw Exception("invalid register access width");
00164     }
00165 }
00166 
00168 template<size_t Len>
00169 void writeRegister(const RegisterDescriptor &reg, const ValueType<Len> &value) {
00170     switch (Len) {
00171         case 1:
00172             // Only FLAGS/EFLAGS bits have a size of one.  Other registers cannot be accessed at this granularity.
00173             if (reg.get_major()!=x86_regclass_flags)
00174                 throw Exception("bit access only valid for FLAGS/EFLAGS register");
00175             if (reg.get_minor()!=0 || reg.get_offset()>=cur_state.n_flags)
00176                 throw Exception("register not implemented in semantic policy");
00177             if (reg.get_nbits()!=1)
00178                 throw Exception("semantic policy supports only single-bit flags");
00179             cur_state.flag[reg.get_offset()] = unsignedExtend<Len, 1>(value);
00180             break;
00181 
00182         case 8:
00183             // Only general purpose registers can be accessed at byte granularity, and only for offsets 0 and 8.
00184             if (reg.get_major()!=x86_regclass_gpr)
00185                 throw Exception("byte access only valid for general purpose registers.");
00186             if (reg.get_minor()>=cur_state.n_gprs)
00187                 throw Exception("register not implemented in semantic policy");
00188             assert(reg.get_nbits()==8); // we had better be asking for a one-byte register (e.g., "ah", not "ax")
00189             switch (reg.get_offset()) {
00190                 case 0:
00191                     cur_state.gpr[reg.get_minor()] =
00192                         concat(signExtend<Len, 8>(value), extract<8, 32>(cur_state.gpr[reg.get_minor()])); // no-op extend
00193                     break;
00194                 case 8:
00195                     cur_state.gpr[reg.get_minor()] =
00196                         concat(extract<0, 8>(cur_state.gpr[reg.get_minor()]),
00197                                concat(unsignedExtend<Len, 8>(value),
00198                                       extract<16, 32>(cur_state.gpr[reg.get_minor()])));
00199                     break;
00200                 default:
00201                     throw Exception("invalid byte access offset");
00202             }
00203             break;
00204 
00205         case 16:
00206             if (reg.get_nbits()!=16)
00207                 throw Exception("invalid 2-byte register");
00208             if (reg.get_offset()!=0)
00209                 throw Exception("policy does not support non-zero offsets for word granularity register access");
00210             switch (reg.get_major()) {
00211                 case x86_regclass_segment:
00212                     if (reg.get_minor()>=cur_state.n_segregs)
00213                         throw Exception("register not implemented in semantic policy");
00214                     cur_state.segreg[reg.get_minor()] = unsignedExtend<Len, 16>(value);
00215                     break;
00216                 case x86_regclass_gpr:
00217                     if (reg.get_minor()>=cur_state.n_gprs)
00218                         throw Exception("register not implemented in semantic policy");
00219                     cur_state.gpr[reg.get_minor()] =
00220                         concat(unsignedExtend<Len, 16>(value),
00221                                extract<16, 32>(cur_state.gpr[reg.get_minor()]));
00222                     break;
00223                 case x86_regclass_flags:
00224                     if (reg.get_minor()!=0 || cur_state.n_flags<16)
00225                         throw Exception("register not implemented in semantic policy");
00226                     cur_state.flag[0]  = extract<0,  1 >(value);
00227                     cur_state.flag[1]  = extract<1,  2 >(value);
00228                     cur_state.flag[2]  = extract<2,  3 >(value);
00229                     cur_state.flag[3]  = extract<3,  4 >(value);
00230                     cur_state.flag[4]  = extract<4,  5 >(value);
00231                     cur_state.flag[5]  = extract<5,  6 >(value);
00232                     cur_state.flag[6]  = extract<6,  7 >(value);
00233                     cur_state.flag[7]  = extract<7,  8 >(value);
00234                     cur_state.flag[8]  = extract<8,  9 >(value);
00235                     cur_state.flag[9]  = extract<9,  10>(value);
00236                     cur_state.flag[10] = extract<10, 11>(value);
00237                     cur_state.flag[11] = extract<11, 12>(value);
00238                     cur_state.flag[12] = extract<12, 13>(value);
00239                     cur_state.flag[13] = extract<13, 14>(value);
00240                     cur_state.flag[14] = extract<14, 15>(value);
00241                     cur_state.flag[15] = extract<15, 16>(value);
00242                     break;
00243                 default:
00244                     throw Exception("word access not valid for this register type");
00245             }
00246             break;
00247 
00248         case 32:
00249             if (reg.get_offset()!=0)
00250                 throw Exception("policy does not support non-zero offsets for double word granularity register access");
00251             switch (reg.get_major()) {
00252                 case x86_regclass_gpr:
00253                     if (reg.get_minor()>=cur_state.n_gprs)
00254                         throw Exception("register not implemented in semantic policy");
00255                     cur_state.gpr[reg.get_minor()] = signExtend<Len, 32>(value);
00256                     break;
00257                 case x86_regclass_ip:
00258                     if (reg.get_minor()!=0)
00259                         throw Exception("register not implemented in semantic policy");
00260                     EIP_LOCATION = unsignedExtend<Len, 32>(value);
00261                     break;
00262                 case x86_regclass_flags:
00263                     if (reg.get_minor()!=0 || cur_state.n_flags<32)
00264                         throw Exception("register not implemented in semantic policy");
00265                     if (reg.get_nbits()!=32)
00266                         throw Exception("register is not 32 bits");
00267                     writeRegister<16>("flags", unsignedExtend<Len, 16>(value));
00268                     cur_state.flag[16] = extract<16, 17>(value);
00269                     cur_state.flag[17] = extract<17, 18>(value);
00270                     cur_state.flag[18] = extract<18, 19>(value);
00271                     cur_state.flag[19] = extract<19, 20>(value);
00272                     cur_state.flag[20] = extract<20, 21>(value);
00273                     cur_state.flag[21] = extract<21, 22>(value);
00274                     cur_state.flag[22] = extract<22, 23>(value);
00275                     cur_state.flag[23] = extract<23, 24>(value);
00276                     cur_state.flag[24] = extract<24, 25>(value);
00277                     cur_state.flag[25] = extract<25, 26>(value);
00278                     cur_state.flag[26] = extract<26, 27>(value);
00279                     cur_state.flag[27] = extract<27, 28>(value);
00280                     cur_state.flag[28] = extract<28, 29>(value);
00281                     cur_state.flag[29] = extract<29, 30>(value);
00282                     cur_state.flag[30] = extract<30, 31>(value);
00283                     cur_state.flag[31] = extract<31, 32>(value);
00284                     break;
00285                 default:
00286                     throw Exception("double word access not valid for this register type");
00287             }
00288             break;
00289 
00290         default:
00291             throw Exception("invalid register access width");
00292     }
00293 }
00294 
00295 #undef EIP_LOCATION

Generated on Wed May 16 06:18:11 2012 for ROSE by  doxygen 1.4.7