tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Register.c (9403B)


      1 /***************************************************************************************************
      2 
      3  Zyan Disassembler Library (Zydis)
      4 
      5  Original Author : Florian Bernd
      6 
      7 * Permission is hereby granted, free of charge, to any person obtaining a copy
      8 * of this software and associated documentation files (the "Software"), to deal
      9 * in the Software without restriction, including without limitation the rights
     10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     11 * copies of the Software, and to permit persons to whom the Software is
     12 * furnished to do so, subject to the following conditions:
     13 *
     14 * The above copyright notice and this permission notice shall be included in all
     15 * copies or substantial portions of the Software.
     16 *
     17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     23 * SOFTWARE.
     24 
     25 ***************************************************************************************************/
     26 
     27 #include "zydis/Zydis/Register.h"
     28 
     29 /* ============================================================================================== */
     30 /* Register strings                                                                               */
     31 /* ============================================================================================== */
     32 
     33 #include "zydis/Zydis/Generated/EnumRegister.inc"
     34 
     35 /* ============================================================================================== */
     36 /* Register-class mapping                                                                         */
     37 /* ============================================================================================== */
     38 
     39 /**
     40 * Defines the `ZydisRegisterMapItem` struct.
     41 */
     42 typedef struct ZydisRegisterLookupItem
     43 {
     44    /**
     45     * The register class.
     46     */
     47    ZydisRegisterClass class;
     48    /**
     49     * The register id.
     50     */
     51    ZyanI8 id;
     52    /**
     53     * The width of register 16- and 32-bit mode.
     54     */
     55    ZydisRegisterWidth width;
     56    /**
     57     * The width of register in 64-bit mode.
     58     */
     59    ZydisRegisterWidth width64;
     60 } ZydisRegisterLookupItem;
     61 
     62 #include "zydis/Zydis/Generated/RegisterLookup.inc"
     63 
     64 /**
     65 * Defines the `ZydisRegisterClassLookupItem` struct.
     66 */
     67 typedef struct ZydisRegisterClassLookupItem_
     68 {
     69    /**
     70     * The lowest register of the current class.
     71     */
     72    ZydisRegister lo;
     73    /**
     74     * The highest register of the current class.
     75     */
     76    ZydisRegister hi;
     77    /**
     78     * The width of registers of the current class in 16- and 32-bit mode.
     79     */
     80    ZydisRegisterWidth width;
     81    /**
     82     * The width of registers of the current class in 64-bit mode.
     83     */
     84    ZydisRegisterWidth width64;
     85 } ZydisRegisterClassLookupItem;
     86 
     87 #include "zydis/Zydis/Generated/RegisterClassLookup.inc"
     88 
     89 /* ============================================================================================== */
     90 /* Exported functions                                                                             */
     91 /* ============================================================================================== */
     92 
     93 /* ---------------------------------------------------------------------------------------------- */
     94 /* Register                                                                                       */
     95 /* ---------------------------------------------------------------------------------------------- */
     96 
     97 ZydisRegister ZydisRegisterEncode(ZydisRegisterClass register_class, ZyanU8 id)
     98 {
     99    if ((register_class == ZYDIS_REGCLASS_INVALID) ||
    100        (register_class == ZYDIS_REGCLASS_FLAGS) ||
    101        (register_class == ZYDIS_REGCLASS_IP))
    102    {
    103        return ZYDIS_REGISTER_NONE;
    104    }
    105 
    106    if ((ZyanUSize)register_class >= ZYAN_ARRAY_LENGTH(REG_CLASS_LOOKUP))
    107    {
    108        return ZYDIS_REGISTER_NONE;
    109    }
    110 
    111    const ZydisRegisterClassLookupItem* item = &REG_CLASS_LOOKUP[register_class];
    112    if (id <= (item->hi - item->lo))
    113    {
    114        return item->lo + id;
    115    }
    116 
    117    return ZYDIS_REGISTER_NONE;
    118 }
    119 
    120 ZyanI8 ZydisRegisterGetId(ZydisRegister reg)
    121 {
    122    if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(REG_LOOKUP))
    123    {
    124        return -1;
    125    }
    126 
    127    return REG_LOOKUP[reg].id;
    128 }
    129 
    130 ZydisRegisterClass ZydisRegisterGetClass(ZydisRegister reg)
    131 {
    132    if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(REG_LOOKUP))
    133    {
    134        return ZYDIS_REGCLASS_INVALID;
    135    }
    136 
    137    return REG_LOOKUP[reg].class;
    138 }
    139 
    140 ZydisRegisterWidth ZydisRegisterGetWidth(ZydisMachineMode mode, ZydisRegister reg)
    141 {
    142    if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(REG_LOOKUP))
    143    {
    144        return 0;
    145    }
    146 
    147    return (mode == ZYDIS_MACHINE_MODE_LONG_64)
    148        ? REG_LOOKUP[reg].width64
    149        : REG_LOOKUP[reg].width;
    150 }
    151 
    152 ZydisRegister ZydisRegisterGetLargestEnclosing(ZydisMachineMode mode, ZydisRegister reg)
    153 {
    154    if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(REG_LOOKUP))
    155    {
    156        return ZYDIS_REGISTER_NONE;
    157    }
    158 
    159    if (mode > ZYDIS_MACHINE_MODE_MAX_VALUE)
    160    {
    161        return ZYDIS_REGISTER_NONE;
    162    }
    163 
    164    const ZydisRegisterClass reg_class = REG_LOOKUP[reg].class;
    165 
    166    if ((reg_class == ZYDIS_REGCLASS_INVALID) ||
    167        ((reg_class == ZYDIS_REGCLASS_GPR64) && (mode != ZYDIS_MACHINE_MODE_LONG_64)))
    168    {
    169        return ZYDIS_REGISTER_NONE;
    170    }
    171 
    172    static const ZydisRegister STATIC_MAPPING[ZYDIS_REGCLASS_MAX_VALUE + 1][3] =
    173    {
    174                                 /* 16              */ /* 32               */ /* 64                  */
    175        [ZYDIS_REGCLASS_FLAGS] = { ZYDIS_REGISTER_FLAGS, ZYDIS_REGISTER_EFLAGS, ZYDIS_REGISTER_RFLAGS },
    176        [ZYDIS_REGCLASS_IP   ] = { ZYDIS_REGISTER_IP   , ZYDIS_REGISTER_EIP   , ZYDIS_REGISTER_RIP    },
    177    };
    178    ZYAN_ASSERT(reg_class < ZYAN_ARRAY_LENGTH(STATIC_MAPPING));
    179 
    180    ZyanU8 mode_bits;
    181    switch (mode)
    182    {
    183    case ZYDIS_MACHINE_MODE_LONG_64:
    184        mode_bits = 2;
    185        break;
    186    case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:
    187    case ZYDIS_MACHINE_MODE_LEGACY_32:
    188        mode_bits = 1;
    189        break;
    190    case ZYDIS_MACHINE_MODE_LONG_COMPAT_16:
    191    case ZYDIS_MACHINE_MODE_LEGACY_16:
    192    case ZYDIS_MACHINE_MODE_REAL_16:
    193        mode_bits = 0;
    194        break;
    195    default:
    196        ZYAN_UNREACHABLE;
    197    }
    198 
    199    const ZydisRegister static_reg = STATIC_MAPPING[reg_class][mode_bits];
    200    if (static_reg != ZYDIS_REGISTER_NONE)
    201    {
    202        return static_reg;
    203    }
    204 
    205    static const ZyanU8 GPR8_MAPPING[20] =
    206    {
    207        /* AL   */  0,
    208        /* CL   */  1,
    209        /* DL   */  2,
    210        /* BL   */  3,
    211        /* AH   */  0,
    212        /* CH   */  1,
    213        /* DH   */  2,
    214        /* BH   */  3,
    215        /* SPL  */  4,
    216        /* BPL  */  5,
    217        /* SIL  */  6,
    218        /* DIL  */  7,
    219        /* R8B  */  8,
    220        /* R9B  */  9,
    221        /* R10B */ 10,
    222        /* R11B */ 11,
    223        /* R12B */ 12,
    224        /* R13B */ 13,
    225        /* R14B */ 14,
    226        /* R15B */ 15
    227    };
    228 
    229    ZyanU8 reg_id = REG_LOOKUP[reg].id;
    230    switch (reg_class)
    231    {
    232    case ZYDIS_REGCLASS_GPR8:
    233        reg_id = GPR8_MAPPING[reg_id];
    234        ZYAN_FALLTHROUGH;
    235    case ZYDIS_REGCLASS_GPR16:
    236    case ZYDIS_REGCLASS_GPR32:
    237    case ZYDIS_REGCLASS_GPR64:
    238        switch (mode_bits)
    239        {
    240        case 2:
    241            return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_GPR64].lo + reg_id;
    242        case 1:
    243            return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_GPR32].lo + reg_id;
    244        case 0:
    245            return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_GPR16].lo + reg_id;
    246        default:
    247            ZYAN_UNREACHABLE;
    248        }
    249    case ZYDIS_REGCLASS_XMM:
    250    case ZYDIS_REGCLASS_YMM:
    251    case ZYDIS_REGCLASS_ZMM:
    252 #if defined(ZYDIS_DISABLE_AVX512) && defined(ZYDIS_DISABLE_KNC)
    253        return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_YMM].lo + reg_id;
    254 #else
    255        return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_ZMM].lo + reg_id;
    256 #endif
    257    default:
    258        return ZYDIS_REGISTER_NONE;
    259    }
    260 }
    261 
    262 const char* ZydisRegisterGetString(ZydisRegister reg)
    263 {
    264    if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(STR_REGISTERS))
    265    {
    266        return ZYAN_NULL;
    267    }
    268 
    269    return STR_REGISTERS[reg].data;
    270 }
    271 
    272 const ZydisShortString* ZydisRegisterGetStringWrapped(ZydisRegister reg)
    273 {
    274    if ((ZyanUSize)reg >= ZYAN_ARRAY_LENGTH(STR_REGISTERS))
    275    {
    276        return ZYAN_NULL;
    277    }
    278 
    279    return &STR_REGISTERS[reg];
    280 }
    281 
    282 /* ---------------------------------------------------------------------------------------------- */
    283 /* Register class                                                                                 */
    284 /* ---------------------------------------------------------------------------------------------- */
    285 
    286 ZydisRegisterWidth ZydisRegisterClassGetWidth(ZydisMachineMode mode,
    287    ZydisRegisterClass register_class)
    288 {
    289    if ((ZyanUSize)register_class >= ZYAN_ARRAY_LENGTH(REG_CLASS_LOOKUP))
    290    {
    291        return 0;
    292    }
    293 
    294    return (mode == ZYDIS_MACHINE_MODE_LONG_64)
    295        ? REG_CLASS_LOOKUP[register_class].width64
    296        : REG_CLASS_LOOKUP[register_class].width;
    297 }
    298 
    299 /* ---------------------------------------------------------------------------------------------- */
    300 
    301 /* ============================================================================================== */