tor-browser

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

Segment.c (7005B)


      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/Zycore/LibC.h"
     28 #include "zydis/Zydis/Segment.h"
     29 
     30 /* ============================================================================================== */
     31 /* Exported functions                                                                             */
     32 /* ============================================================================================== */
     33 
     34 ZyanStatus ZydisGetInstructionSegments(const ZydisDecodedInstruction* instruction,
     35    ZydisInstructionSegments* segments)
     36 {
     37    if (!instruction || !segments)
     38    {
     39        return ZYAN_STATUS_INVALID_ARGUMENT;
     40    }
     41 
     42    ZYAN_MEMSET(segments, 0, sizeof(*segments));
     43 
     44    // Legacy prefixes and `REX`
     45    if (instruction->raw.prefix_count)
     46    {
     47        const ZyanU8 rex_offset = (instruction->attributes & ZYDIS_ATTRIB_HAS_REX) ? 1 : 0;
     48        if (!rex_offset || (instruction->raw.prefix_count > 1))
     49        {
     50            segments->segments[segments->count  ].type   = ZYDIS_INSTR_SEGMENT_PREFIXES;
     51            segments->segments[segments->count  ].offset = 0;
     52            segments->segments[segments->count++].size   =
     53                instruction->raw.prefix_count - rex_offset;
     54        }
     55        if (rex_offset)
     56        {
     57            segments->segments[segments->count  ].type   = ZYDIS_INSTR_SEGMENT_REX;
     58            segments->segments[segments->count  ].offset =
     59                instruction->raw.prefix_count - rex_offset;
     60            segments->segments[segments->count++].size   = 1;
     61        }
     62    }
     63 
     64    // Encoding prefixes
     65    ZydisInstructionSegment segment_type = ZYDIS_INSTR_SEGMENT_NONE;
     66    ZyanU8 segment_offset = 0;
     67    ZyanU8 segment_size = 0;
     68    switch (instruction->encoding)
     69    {
     70    case ZYDIS_INSTRUCTION_ENCODING_XOP:
     71        segment_type = ZYDIS_INSTR_SEGMENT_XOP;
     72        segment_offset = instruction->raw.xop.offset;
     73        segment_size = 3;
     74        break;
     75    case ZYDIS_INSTRUCTION_ENCODING_VEX:
     76        segment_type = ZYDIS_INSTR_SEGMENT_VEX;
     77        segment_offset = instruction->raw.vex.offset;
     78        segment_size = instruction->raw.vex.size;
     79        break;
     80    case ZYDIS_INSTRUCTION_ENCODING_EVEX:
     81        segment_type = ZYDIS_INSTR_SEGMENT_EVEX;
     82        segment_offset = instruction->raw.evex.offset;
     83        segment_size = 4;
     84        break;
     85    case ZYDIS_INSTRUCTION_ENCODING_MVEX:
     86        segment_type = ZYDIS_INSTR_SEGMENT_MVEX;
     87        segment_offset = instruction->raw.mvex.offset;
     88        segment_size = 4;
     89        break;
     90    default:
     91        break;
     92    }
     93    if (segment_type)
     94    {
     95        segments->segments[segments->count  ].type   = segment_type;
     96        segments->segments[segments->count  ].offset = segment_offset;
     97        segments->segments[segments->count++].size   = segment_size;
     98    }
     99 
    100    // Opcode
    101    segment_size = 1;
    102    if ((instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_LEGACY) ||
    103        (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_3DNOW))
    104    {
    105        switch (instruction->opcode_map)
    106        {
    107        case ZYDIS_OPCODE_MAP_DEFAULT:
    108            break;
    109        case ZYDIS_OPCODE_MAP_0F:
    110            ZYAN_FALLTHROUGH;
    111        case ZYDIS_OPCODE_MAP_0F0F:
    112            segment_size = 2;
    113            break;
    114        case ZYDIS_OPCODE_MAP_0F38:
    115            ZYAN_FALLTHROUGH;
    116        case ZYDIS_OPCODE_MAP_0F3A:
    117            segment_size = 3;
    118            break;
    119        default:
    120        ZYAN_UNREACHABLE;
    121        }
    122    }
    123    segments->segments[segments->count  ].type = ZYDIS_INSTR_SEGMENT_OPCODE;
    124    if (segments->count)
    125    {
    126        segments->segments[segments->count].offset =
    127                segments->segments[segments->count - 1].offset +
    128                segments->segments[segments->count - 1].size;
    129    } else
    130    {
    131        segments->segments[segments->count].offset = 0;
    132    }
    133    segments->segments[segments->count++].size = segment_size;
    134 
    135    // ModRM
    136    if (instruction->attributes & ZYDIS_ATTRIB_HAS_MODRM)
    137    {
    138        segments->segments[segments->count  ].type = ZYDIS_INSTR_SEGMENT_MODRM;
    139        segments->segments[segments->count  ].offset = instruction->raw.modrm.offset;
    140        segments->segments[segments->count++].size = 1;
    141    }
    142 
    143    // SIB
    144    if (instruction->attributes & ZYDIS_ATTRIB_HAS_SIB)
    145    {
    146        segments->segments[segments->count  ].type = ZYDIS_INSTR_SEGMENT_SIB;
    147        segments->segments[segments->count  ].offset = instruction->raw.sib.offset;
    148        segments->segments[segments->count++].size = 1;
    149    }
    150 
    151    // Displacement
    152    if (instruction->raw.disp.size)
    153    {
    154        segments->segments[segments->count  ].type = ZYDIS_INSTR_SEGMENT_DISPLACEMENT;
    155        segments->segments[segments->count  ].offset = instruction->raw.disp.offset;
    156        segments->segments[segments->count++].size = instruction->raw.disp.size / 8;
    157    }
    158 
    159    // Immediates
    160    for (ZyanU8 i = 0; i < 2; ++i)
    161    {
    162        if (instruction->raw.imm[i].size)
    163        {
    164            segments->segments[segments->count  ].type = ZYDIS_INSTR_SEGMENT_IMMEDIATE;
    165            segments->segments[segments->count  ].offset = instruction->raw.imm[i].offset;
    166            segments->segments[segments->count++].size = instruction->raw.imm[i].size / 8;
    167        }
    168    }
    169 
    170    if (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_3DNOW)
    171    {
    172        segments->segments[segments->count].type = ZYDIS_INSTR_SEGMENT_OPCODE;
    173        segments->segments[segments->count].offset = instruction->length -1;
    174        segments->segments[segments->count++].size = 1;
    175    }
    176 
    177    return ZYAN_STATUS_SUCCESS;
    178 }
    179 
    180 /* ---------------------------------------------------------------------------------------------- */
    181 
    182 /* ============================================================================================== */