bytecode_local.h
Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) 2009-2010 Sourcefire, Inc.
00003  *  All rights reserved.
00004  *  Authors: Török Edvin
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  *
00015  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00016  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00018  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00019  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00020  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00021  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00022  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00023  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00024  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00025  * SUCH DAMAGE.
00026  */
00027 
00029 #define force_inline inline __attribute__((always_inline))
00030 #define overloadable_func __attribute__((overloadable))
00031 
00032 /* DOXYGEN defined() must come first */
00033 #if defined(DOXYGEN) || __has_feature(attribute_overloadable)
00034 /* Yes, clang supports overloading functions in C! */
00037 static force_inline void overloadable_func debug(const char * str)
00038 {
00039     debug_print_str((const uint8_t*)str, 0);
00040 }
00041 
00044 static force_inline void overloadable_func debug(const uint8_t* str)
00045 {
00046     debug_print_str((const uint8_t*)str, 0);
00047 }
00048 
00051 static force_inline void overloadable_func debug(uint32_t a)
00052 {
00053     debug_print_uint(a);
00054 }
00055 
00058 void debug(...) __attribute__((overloadable, unavailable));
00059 #endif
00060 
00061 
00062 /* Virusname definition handling */
00068 #define VIRUSNAME_PREFIX(name) const char __clambc_virusname_prefix[] = name;
00069 
00072 #define VIRUSNAMES(...) const char *const __clambc_virusnames[] = {__VA_ARGS__};
00073 
00074 /* Logical signature handling */
00075 
00076 typedef struct signature {
00077     uint64_t id;
00078 } __Signature;
00079 
00083 #define PE_UNPACKER_DECLARE const uint16_t __clambc_kind = BC_PE_UNPACKER;
00084 
00091 #define PDF_HOOK_DECLARE const uint16_t __clambc_kind = BC_PDF;
00092 
00095 #define BYTECODE_ABORT_HOOK 0xcea5e
00096 
00102 #define PE_HOOK_DECLARE const uint16_t __clambc_kind = BC_PE_ALL;
00103 
00106 #define SIGNATURES_DECL_BEGIN \
00107     struct __Signatures {
00108 
00110 #define DECLARE_SIGNATURE(name) \
00111     const char *name##_sig;\
00112     __Signature name;
00113 
00115 #define SIGNATURES_DECL_END };
00116 
00120 #define TARGET(tgt) const unsigned short __Target = (tgt);
00121 
00125 #define COPYRIGHT(c) const char *const __Copyright = (c);
00126 
00133 #define ICONGROUP1(group) const char *const __IconGroup1 = (group);
00134 
00139 #define ICONGROUP2(group) const char *const __IconGroup2 = (group);
00140 
00147 #define FUNCTIONALITY_LEVEL_MIN(m) const unsigned short __FuncMin = (m);
00148 
00154 #define FUNCTIONALITY_LEVEL_MAX(m) const unsigned short __FuncMax = (m);
00155 
00156 #define LDB_ADDATTRIBUTES(x) const char * __ldb_rawattrs = (x);
00157 
00161 /* some other macro may use __COUNTER__, so we need to subtract its current\
00162  * value to obtain zero-based indices */
00163 #define SIGNATURES_DEF_BEGIN \
00164     static const unsigned __signature_bias = __COUNTER__+1;\
00165 const struct __Signatures Signatures = {\
00166 
00172 #define DEFINE_SIGNATURE(name, hex) \
00173     .name##_sig = (hex),\
00174     .name = {__COUNTER__ - __signature_bias},
00175 
00177 #define SIGNATURES_END };\
00178 
00179 
00186 static force_inline uint32_t count_match(__Signature sig)\
00187 { return __clambc_match_counts[sig.id]; }\
00188 
00193 static force_inline uint32_t matches(__Signature sig)\
00194 { return __clambc_match_counts[sig.id]  != 0; }\
00195 
00196 
00203 static force_inline uint32_t match_location(__Signature sig, uint32_t goback)
00204 {
00205   int32_t pos = __clambc_match_offsets[sig.id];
00206   if (engine_functionality_level() <= FUNC_LEVEL_096_1) {
00207     /* bug, it returns offset of last subsig, not offset of first */
00208     pos -= goback;
00209     if (pos <= 0) pos = 0;
00210   }
00211   return pos;
00212 }
00213 
00225 static force_inline int32_t match_location_check(__Signature sig,
00226                                                   uint32_t goback,
00227                                                   const char *static_start,
00228                                                   uint32_t static_len)
00229 {
00230   int32_t pos = match_location(sig, goback);
00231   if (seek(pos, SEEK_SET) != pos)
00232     return -1;
00233   int32_t cpos = file_find_limit(static_start, static_len, pos + goback);
00234   if (cpos == -1) {
00235     debug("Engine reported match, but we couldn't find it! Engine reported (after fixup):");
00236     debug(pos);
00237     return -1;
00238   }
00239   if (seek(cpos, SEEK_SET) != cpos)
00240     return -1;
00241   if (cpos != pos && engine_functionality_level() >= FUNC_LEVEL_096_1_dev) {
00242     debug("wrong match pos reported by engine, real match pos:");
00243     debug(cpos);
00244     debug("reported by engine:");
00245     debug(pos);
00246     debug("but goback fixed it up!");
00247   }
00248   return cpos;
00249 }
00250 
00256 static force_inline overloadable_func void foundVirus(const char *virusname)
00257 {
00258     setvirusname((const uint8_t*)virusname, 0);
00259 }
00260 
00261 #if defined(DOXYGEN) || __has_feature(attribute_overloadable)
00262 
00263 static force_inline void overloadable_func foundVirus(void)
00264 {
00265   foundVirus("");
00266 }
00267 #endif
00268 
00272 static force_inline uint32_t getFilesize(void)
00273 {
00274   return __clambc_filesize[0];
00275 }
00276 
00277 union unaligned_32 {
00278         uint32_t una_u32;
00279         int32_t una_s32;
00280 } __attribute__((packed));
00281 
00282 union unaligned_16 {
00283         uint16_t una_u16;
00284         int16_t una_s16;
00285 } __attribute__((packed));
00286 
00303 bool __is_bigendian(void) __attribute__((const)) __attribute__((nothrow));
00304 
00310 static uint32_t force_inline le32_to_host(uint32_t v)
00311 {
00312   /* calculate bswap always, so compiler can use a select,
00313      and doesn't need to create a branch.
00314      This will get optimized away at bytecode load time anyway */
00315   uint32_t swapped = __builtin_bswap32(v);
00316   return __is_bigendian() ? swapped : v;
00317 }
00318 
00324 static uint64_t force_inline le64_to_host(uint64_t v)
00325 {
00326   uint64_t swapped = __builtin_bswap64(v);
00327   return __is_bigendian() ? swapped : v;
00328 }
00329 
00335 static uint16_t force_inline le16_to_host(uint16_t v)
00336 {
00337   uint16_t swapped = ((v & 0xff) << 8) | ((v >> 8) & 0xff);
00338   return __is_bigendian() ? swapped : v;
00339 }
00340 
00345 static uint32_t force_inline cli_readint32(const void* buff)
00346 {
00347     uint32_t v = ((const union unaligned_32 *)buff)->una_s32;
00348     return le32_to_host(v);
00349 }
00350 
00355 static uint16_t force_inline cli_readint16(const void* buff)
00356 {
00357     uint16_t v = ((const union unaligned_16 *)buff)->una_s16;
00358     return le16_to_host(v);
00359 }
00360 
00365 static void force_inline cli_writeint32(void* offset, uint32_t v)
00366 {
00367     ((union unaligned_32 *)offset)->una_u32 = le32_to_host(v);
00368 }
00369 
00370 /* --------------------- PE helper functions ------------------------ */
00374 static force_inline bool hasExeInfo(void)
00375 {
00376     return __clambc_pedata.offset != -1;
00377 }
00378 
00382 static force_inline bool hasPEInfo(void)
00383 {
00384   return (__clambc_kind == BC_PE_ALL ||
00385           __clambc_kind == BC_PE_UNPACKER);
00386 }
00387 
00388 #define NEED_PE_INFO {  /* only available in PE hooks */\
00389   if (!hasPEInfo())\
00390     __fail_missing_PE_HOOK_DECLARE__or__PE_UNPACKER_DECLARE();\
00391 }
00392 
00397 static force_inline bool isPE64(void)
00398 {
00399   NEED_PE_INFO;
00400   return le16_to_host(__clambc_pedata.opt64.Magic) == 0x020b;
00401 }
00402 
00403 static force_inline
00407 static force_inline uint8_t getPEMajorLinkerVersion(void)
00408 {
00409   return isPE64() ?
00410     __clambc_pedata.opt64.MajorLinkerVersion :
00411     __clambc_pedata.opt32.MajorLinkerVersion;
00412 }
00413 
00417 static force_inline uint8_t getPEMinorLinkerVersion(void)
00418 {
00419   return isPE64() ?
00420     __clambc_pedata.opt64.MinorLinkerVersion :
00421     __clambc_pedata.opt32.MinorLinkerVersion;
00422 }
00423 
00427 static force_inline uint32_t getPESizeOfCode(void)
00428 {
00429   return le32_to_host(isPE64() ?
00430                       __clambc_pedata.opt64.SizeOfCode :
00431                       __clambc_pedata.opt32.SizeOfCode);
00432 }
00433 
00437 static force_inline uint32_t getPESizeOfInitializedData(void)
00438 {
00439   return le32_to_host(isPE64() ?
00440                       __clambc_pedata.opt64.SizeOfInitializedData :
00441                       __clambc_pedata.opt32.SizeOfInitializedData);
00442 }
00443 
00447 static force_inline uint32_t getPESizeOfUninitializedData(void)
00448 {
00449   return le32_to_host(isPE64() ?
00450                       __clambc_pedata.opt64.SizeOfUninitializedData :
00451                       __clambc_pedata.opt32.SizeOfUninitializedData);
00452 }
00453 
00458 static force_inline uint32_t getPEBaseOfCode(void)
00459 {
00460   return le32_to_host(isPE64() ?
00461                       __clambc_pedata.opt64.BaseOfCode :
00462                       __clambc_pedata.opt32.BaseOfCode);
00463 }
00464 
00469 static force_inline uint32_t getPEBaseOfData(void)
00470 {
00471   return le32_to_host(isPE64() ?
00472                       0 :
00473                       __clambc_pedata.opt32.BaseOfData);
00474 }
00475 
00479 static force_inline uint64_t getPEImageBase(void)
00480 {
00481   return le64_to_host(isPE64() ?
00482                       __clambc_pedata.opt64.ImageBase :
00483                       __clambc_pedata.opt32.ImageBase);
00484 }
00485 
00489 static force_inline uint32_t getPESectionAlignment(void)
00490 {
00491   return le32_to_host(isPE64() ?
00492                       __clambc_pedata.opt64.SectionAlignment :
00493                       __clambc_pedata.opt32.SectionAlignment);
00494 }
00495 
00500 static force_inline uint32_t getPEFileAlignment(void)
00501 {
00502   return le32_to_host(isPE64() ?
00503                       __clambc_pedata.opt64.FileAlignment :
00504                       __clambc_pedata.opt32.FileAlignment);
00505 }
00506 
00510 static force_inline uint16_t getPEMajorOperatingSystemVersion(void)
00511 {
00512   return le16_to_host(isPE64() ?
00513                       __clambc_pedata.opt64.MajorOperatingSystemVersion :
00514                       __clambc_pedata.opt32.MajorOperatingSystemVersion);
00515 }
00516 
00520 static force_inline uint16_t getPEMinorOperatingSystemVersion(void)
00521 {
00522   return le16_to_host(isPE64() ?
00523                       __clambc_pedata.opt64.MinorOperatingSystemVersion :
00524                       __clambc_pedata.opt32.MinorOperatingSystemVersion);
00525 }
00526 
00530 static force_inline uint16_t getPEMajorImageVersion(void)
00531 {
00532   return le16_to_host(isPE64() ?
00533                       __clambc_pedata.opt64.MajorImageVersion :
00534                       __clambc_pedata.opt32.MajorImageVersion);
00535 }
00536 
00540 static force_inline uint16_t getPEMinorImageVersion(void)
00541 {
00542   return le16_to_host(isPE64() ?
00543                       __clambc_pedata.opt64.MinorImageVersion :
00544                       __clambc_pedata.opt32.MinorImageVersion);
00545 }
00546 
00550 static force_inline uint16_t getPEMajorSubsystemVersion(void)
00551 {
00552   return le16_to_host(isPE64() ?
00553                       __clambc_pedata.opt64.MajorSubsystemVersion :
00554                       __clambc_pedata.opt32.MajorSubsystemVersion);
00555 }
00556 
00560 static force_inline uint16_t getPEMinorSubsystemVersion(void)
00561 {
00562   return le16_to_host(isPE64() ?
00563                       __clambc_pedata.opt64.MinorSubsystemVersion :
00564                       __clambc_pedata.opt32.MinorSubsystemVersion);
00565 }
00566 
00570 static force_inline uint32_t getPEWin32VersionValue(void)
00571 {
00572   return le32_to_host(isPE64() ?
00573                       __clambc_pedata.opt64.Win32VersionValue :
00574                       __clambc_pedata.opt32.Win32VersionValue);
00575 }
00576 
00580 static force_inline uint32_t getPESizeOfImage(void)
00581 {
00582   return le32_to_host(isPE64() ?
00583                       __clambc_pedata.opt64.SizeOfImage :
00584                       __clambc_pedata.opt32.SizeOfImage);
00585 }
00586 
00590 static force_inline uint32_t getPESizeOfHeaders(void)
00591 {
00592   return le32_to_host(isPE64() ?
00593                       __clambc_pedata.opt64.SizeOfHeaders :
00594                       __clambc_pedata.opt32.SizeOfHeaders);
00595 }
00596 
00601 static force_inline uint32_t getPECheckSum(void)
00602 {
00603   return le32_to_host(isPE64() ?
00604                       __clambc_pedata.opt64.CheckSum :
00605                       __clambc_pedata.opt32.CheckSum);
00606 }
00607 
00611 static force_inline uint16_t getPESubsystem(void)
00612 {
00613   return le16_to_host(isPE64() ?
00614                       __clambc_pedata.opt64.Subsystem :
00615                       __clambc_pedata.opt32.Subsystem);
00616 }
00617 
00622 static force_inline uint16_t getPEDllCharacteristics(void)
00623 {
00624   return le16_to_host(isPE64() ?
00625                       __clambc_pedata.opt64.DllCharacteristics :
00626                       __clambc_pedata.opt32.DllCharacteristics);
00627 }
00628 
00632 static force_inline uint32_t getPESizeOfStackReserve(void)
00633 {
00634   return le32_to_host(isPE64() ?
00635                       __clambc_pedata.opt64.SizeOfStackReserve :
00636                       __clambc_pedata.opt32.SizeOfStackReserve);
00637 }
00638 
00642 static force_inline uint32_t getPESizeOfStackCommit(void)
00643 {
00644   return le32_to_host(isPE64() ?
00645                       __clambc_pedata.opt64.SizeOfStackCommit :
00646                       __clambc_pedata.opt32.SizeOfStackCommit);
00647 }
00648 
00652 static force_inline uint32_t getPESizeOfHeapReserve(void)
00653 {
00654   return le32_to_host(isPE64() ?
00655                       __clambc_pedata.opt64.SizeOfHeapReserve :
00656                       __clambc_pedata.opt32.SizeOfHeapReserve);
00657 }
00658 
00662 static force_inline uint32_t getPESizeOfHeapCommit(void)
00663 {
00664   return le32_to_host(isPE64() ?
00665                       __clambc_pedata.opt64.SizeOfHeapCommit :
00666                       __clambc_pedata.opt32.SizeOfHeapCommit);
00667 }
00668 
00673 static force_inline uint32_t getPELoaderFlags(void)
00674 {
00675   return le32_to_host(isPE64() ?
00676                       __clambc_pedata.opt64.LoaderFlags :
00677                       __clambc_pedata.opt32.LoaderFlags);
00678 }
00679 
00684 static force_inline uint16_t getPEMachine()
00685 {
00686   NEED_PE_INFO;
00687   return le16_to_host(__clambc_pedata.file_hdr.Machine);
00688 }
00689 
00693 static force_inline uint32_t getPETimeDateStamp()
00694 {
00695   NEED_PE_INFO;
00696   return le32_to_host(__clambc_pedata.file_hdr.TimeDateStamp);
00697 }
00698 
00702 static force_inline uint32_t getPEPointerToSymbolTable()
00703 {
00704   NEED_PE_INFO;
00705   return le32_to_host(__clambc_pedata.file_hdr.PointerToSymbolTable);
00706 }
00707 
00711 static force_inline uint32_t getPENumberOfSymbols()
00712 {
00713   NEED_PE_INFO;
00714   return le32_to_host(__clambc_pedata.file_hdr.NumberOfSymbols);
00715 }
00716 
00721 static force_inline uint16_t getPESizeOfOptionalHeader()
00722 {
00723   NEED_PE_INFO;
00724   return le16_to_host(__clambc_pedata.file_hdr.SizeOfOptionalHeader);
00725 }
00726 
00731 static force_inline uint16_t getPECharacteristics()
00732 {
00733   NEED_PE_INFO;
00734   return le16_to_host(__clambc_pedata.file_hdr.Characteristics);
00735 }
00736 
00743 static force_inline bool getPEisDLL()
00744 {
00745   return getPECharacteristics() & 0x2000;
00746 }
00747 
00753 static force_inline uint32_t getPEDataDirRVA(unsigned n)
00754 {
00755   NEED_PE_INFO;
00756   struct pe_image_data_dir *p = &__clambc_pedata.opt64.DataDirectory[n];
00757   struct pe_image_data_dir *p32 = &__clambc_pedata.opt32.DataDirectory[n];
00758   return n < 16 ? le32_to_host(isPE64() ?
00759                                p->VirtualAddress :
00760                                p32->VirtualAddress)
00761     : 0;
00762 }
00763 
00769 static force_inline uint32_t getPEDataDirSize(unsigned n)
00770 {
00771   NEED_PE_INFO;
00772   return n < 16 ? le32_to_host(isPE64() ?
00773                                __clambc_pedata.opt64.DataDirectory[n].Size :
00774                                __clambc_pedata.opt32.DataDirectory[n].Size)
00775     : 0;
00776 }
00777 
00781 static force_inline uint16_t getNumberOfSections(void)
00782 {
00783   /* available in non-PE hooks too */
00784     return __clambc_pedata.nsections;
00785 }
00786 
00790 static uint32_t getPELFANew(void)
00791 {
00792   NEED_PE_INFO;
00793     return le32_to_host(__clambc_pedata.e_lfanew);
00794 }
00795 
00803 static force_inline int readPESectionName(unsigned char name[8], unsigned n)
00804 {
00805   NEED_PE_INFO;
00806   if (n >= getNumberOfSections())
00807     return -1;
00808   uint32_t at = getPELFANew() + sizeof(struct pe_image_file_hdr) + sizeof(struct pe_image_optional_hdr32);
00809   if (!isPE64()) {
00810     /* Seek to the end of the long header */
00811     at += getPESizeOfOptionalHeader() - sizeof(struct pe_image_optional_hdr32);
00812   } else {
00813     at += sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32);
00814   }
00815   at += n * sizeof(struct pe_image_file_hdr);
00816   int32_t pos = seek(at, SEEK_SET);
00817   if (pos == -1)
00818     return -2;
00819   if (read(name, 8) != 8)
00820     return -3;
00821   seek(pos, SEEK_SET);
00822   return 0;
00823 }
00824 
00828 static force_inline uint32_t getEntryPoint(void)
00829 {
00830   /* available in non-PE hooks too */
00831     return __clambc_pedata.ep;
00832 }
00833 
00837 static force_inline uint32_t getExeOffset(void)
00838 {
00839   /* available in non-PE hooks too */
00840     return __clambc_pedata.offset;
00841 }
00842 
00849 static force_inline uint32_t getImageBase(void)
00850 {
00851   NEED_PE_INFO;
00852   return le32_to_host(__clambc_pedata.opt32.ImageBase);
00853 }
00854 
00858 static uint32_t getVirtualEntryPoint(void)
00859 {
00860   NEED_PE_INFO;
00861   return le32_to_host(isPE64() ?
00862                         __clambc_pedata.opt64.AddressOfEntryPoint:
00863                         __clambc_pedata.opt32.AddressOfEntryPoint);
00864 }
00865 
00870 static uint32_t getSectionRVA(unsigned i)
00871 {
00872   struct cli_exe_section section;
00873   if (get_pe_section(&section, i) == -1)
00874     return -1;
00875   return section.rva;
00876 }
00877 
00882 static uint32_t getSectionVirtualSize(unsigned i)
00883 {
00884   struct cli_exe_section section;
00885   if (get_pe_section(&section, i) == -1)
00886     return -1;
00887   return section.vsz;
00888 }
00889 
00899 static force_inline bool readRVA(uint32_t rva, void *buf, size_t bufsize)
00900 {
00901   uint32_t off = pe_rawaddr(rva);
00902   if (off == PE_INVALID_RVA)
00903     return false;
00904   int32_t oldpos = seek(off, SEEK_SET);
00905   if (oldpos == -1)
00906     return false;
00907   if (read(buf, bufsize) != bufsize) {
00908     return false;
00909   }
00910   seek(oldpos, SEEK_SET);
00911   return true;
00912 }
00913 
00914 #ifdef __cplusplus
00915 #define restrict
00916 #endif
00917 
00925 static void* memchr(const void* s, int c, size_t n)
00926 {
00927   unsigned char cc = c;
00928   const char *end, *p = s;
00929 
00930   for (end=p+n; p < end; p++)
00931     if (*p == cc)
00932       return p;
00933   return (void*)0;
00934 }
00935 
00936 /* Provided by LLVM intrinsics */
00943 void* memset(void *src, int c, uintptr_t n) __attribute__((nothrow)) __attribute__((__nonnull__((1))));
00944 
00951 void *memmove (void *dst, const void *src, uintptr_t n)
00952     __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1, 2)));
00959 void *memcpy (void *restrict dst, const void *restrict src, uintptr_t n)
00960     __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1, 2)));
00961 
00970 int memcmp (const void *s1, const void *s2, uint32_t n)
00971     __attribute__ ((__nothrow__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
00972 
00975 struct DIS_mem_arg {
00976     enum DIS_SIZE access_size;
00977     enum X86REGS scale_reg;
00978     enum X86REGS add_reg;
00979     uint8_t scale;
00980     int32_t displacement;
00981 };
00982 
00985 struct DIS_arg {
00986     enum DIS_ACCESS access_type;
00987     enum DIS_SIZE access_size;
00988     union {
00989         struct DIS_mem_arg mem;
00990         enum X86REGS reg;
00991         uint64_t other;
00992     } u;
00993 };
00994 
00997 struct DIS_fixed {
00998     enum X86OPS x86_opcode;
00999     enum DIS_SIZE operation_size;
01000     enum DIS_SIZE address_size;
01001     uint8_t segment;
01002     uint8_t padding1;
01003     uint16_t padding2;
01004     struct DIS_arg arg[3];
01005 };
01006 
01013 static force_inline uint32_t
01014 DisassembleAt(struct DIS_fixed* result, uint32_t offset, uint32_t len)
01015 {
01016     struct DISASM_RESULT res;
01017     unsigned i;
01018     seek(offset, SEEK_SET);
01019     offset = disasm_x86(&res, len);
01020     result->x86_opcode = (enum X86OPS) cli_readint16(&res.real_op);
01021     result->operation_size = (enum DIS_SIZE) res.opsize;
01022     result->address_size = (enum DIS_SIZE) res.adsize;
01023     result->segment = res.segment;
01024     for (i=0;i<3;i++) {
01025         struct DIS_arg *arg = &result->arg[i];
01026         arg->access_type = (enum DIS_ACCESS) res.arg[i][0];
01027         switch (result->arg[i].access_type) {
01028             case ACCESS_MEM:
01029                 arg->u.mem.access_size = (enum DIS_SIZE) res.arg[i][1];
01030                 arg->u.mem.scale_reg = (enum X86REGS) res.arg[i][2];
01031                 arg->u.mem.add_reg = (enum X86REGS) res.arg[i][3];
01032                 arg->u.mem.scale = res.arg[i][4];
01033                 arg->u.mem.displacement = cli_readint32((const uint32_t*)&res.arg[i][6]);
01034                 break;
01035             case ACCESS_REG:
01036                 arg->u.reg = (enum X86REGS) res.arg[i][1];
01037                 break;
01038             default: {
01039                 uint64_t x = cli_readint32((const uint32_t*)&res.arg[i][6]);
01040                 arg->u.other = (x << 32) | cli_readint32((const uint32_t*)&res.arg[i][2]);
01041                 break;
01042             }
01043         }
01044     }
01045     return offset;
01046 }
01047 
01048 // re2c macros
01049 #define RE2C_BSIZE 1024
01050 typedef struct {
01051   unsigned char *cur, *lim, *mrk, *ctx, *eof, *tok;
01052   int res;
01053   int32_t tokstart;
01054   unsigned char buffer[RE2C_BSIZE];
01055 } regex_scanner_t;
01056 
01057 #define YYCTYPE unsigned char
01058 #define YYCURSOR re2c_scur
01059 #define YYLIMIT re2c_slim
01060 #define YYMARKER re2c_smrk
01061 #define YYCONTEXT re2c_sctx
01062 #define YYFILL(n) { \
01063   RE2C_FILLBUFFER(n);\
01064   if (re2c_sres <= 0) break;\
01065 }
01066 
01067 #define REGEX_SCANNER unsigned char *re2c_scur, *re2c_stok, *re2c_smrk, *re2c_sctx, *re2c_slim;\
01068   int re2c_sres; int32_t re2c_stokstart;\
01069   unsigned char re2c_sbuffer[RE2C_BSIZE];\
01070   re2c_scur = re2c_slim = re2c_smrk = re2c_sctx = &re2c_sbuffer[0];\
01071   re2c_sres = 0;\
01072   RE2C_FILLBUFFER(0);
01073 
01074 #define REGEX_POS (-(re2c_slim - re2c_scur) + seek(0, SEEK_CUR))
01075 #define REGEX_LOOP_BEGIN do { re2c_stok = re2c_scur; re2c_stokstart = REGEX_POS;} while (0);
01076 #define REGEX_RESULT (re2c_sres)
01077 
01078 #define RE2C_DEBUG_PRINT \
01079 do {\
01080   char buf[81];\
01081   uint32_t here = seek(0, SEEK_CUR);\
01082   uint32_t d = re2c_slim - re2c_scur;\
01083   uint32_t end = here - d;\
01084   unsigned len = end - re2c_stokstart;\
01085   if (len > 80) {\
01086     unsigned skipped = len - 74;\
01087     seek(re2c_stokstart, SEEK_SET);\
01088     if (read(buf, 37) == 37)\
01089       break;\
01090     memcpy(buf+37, "[...]", 5);\
01091     seek(end-37, SEEK_SET);\
01092     if (read(buf, 37) != 37)\
01093       break;\
01094     buf[80] = '\0';\
01095   } else {\
01096     seek(re2c_stokstart, SEEK_SET);\
01097     if (read(buf, len) != len)\
01098       break;\
01099     buf[len] = '\0';\
01100   }\
01101   buf[80] = '\0';\
01102   debug_print_str(buf, 0);\
01103   seek(here, SEEK_SET);\
01104 } while (0)
01105 
01106 #define DEBUG_PRINT_REGEX_MATCH RE2C_DEBUG_PRINT
01107 
01108 #define BUFFER_FILL(buf, cursor, need, limit) do {\
01109   (limit) = fill_buffer((buf), sizeof((buf)), (limit), (cursor), (need));\
01110 } while (0);
01111 
01112 #define BUFFER_ENSURE(buf, cursor, need, limit) do {\
01113   if ((cursor) + (need) >= (limit)) {\
01114     BUFFER_FILL(buf, cursor, need, limit)\
01115     (cursor) = 0;\
01116   }\
01117 } while (0);
01118 
01119 /* Move stok to offset 0, and fill rest of buffer, at least with 'len' bytes.
01120    Adjust the other pointers, which must be after the stok pointer!
01121 */
01122 #define RE2C_FILLBUFFER(need) do {\
01123   uint32_t cursor = re2c_stok - &re2c_sbuffer[0];\
01124   int32_t limit = re2c_slim - &re2c_sbuffer[0];\
01125   limit = fill_buffer(re2c_sbuffer, sizeof(re2c_sbuffer), limit, (cursor), (need));\
01126   if (!limit) {\
01127     re2c_sres = 0;\
01128   } else if (limit <= (need)) {\
01129      re2c_sres = -1;\
01130   } else {\
01131     uint32_t curoff = re2c_scur - re2c_stok;\
01132     uint32_t mrkoff = re2c_smrk - re2c_stok;\
01133     uint32_t ctxoff = re2c_sctx - re2c_stok;\
01134     re2c_slim = &re2c_sbuffer[0] + limit;\
01135     re2c_stok = &re2c_sbuffer[0];\
01136     re2c_scur = &re2c_sbuffer[0] + curoff;\
01137     re2c_smrk = &re2c_sbuffer[0] + mrkoff;\
01138     re2c_sctx = &re2c_sbuffer[0] + ctxoff;\
01139     re2c_sres = limit;\
01140   }\
01141 } while (0);
01142 
01145 static inline int32_t ilog2_compat(uint32_t a, uint32_t b)
01146 {
01147     uint32_t c = a > b ? a : b;
01148     if (c < 2048) {
01149         // scale up a,b to [0, 4096]
01150         uint32_t scale = 2048/c;
01151         a *= scale;
01152         b *= scale;
01153     } else {
01154         // scale down a,b to [0, 4096]
01155         uint32_t scale = (c+2047) / 2048;
01156         a /= scale;
01157         b /= scale;
01158     }
01159     // log(a/b) = log(a*scale/(b*scale)) = log(a*scale) - log(b*scale)
01160     return ilog_table[a] - ilog_table[b];
01161 }
 All Data Structures Files Functions Variables Enumerations Enumerator Defines