├── ooops_levels.png ├── change_io_on_fly.jpg ├── cal_threshhold.sh ├── src ├── msleep.c ├── test_open.c ├── test_stat.c ├── get_ip.c ├── client.c ├── mpi_aggregator.c ├── t_open_stat.c ├── hook_int.h ├── dict.c ├── set_io_param.c └── hook.c ├── include ├── dict.h ├── hook.h ├── udis86.h ├── utarray.h └── xxhash.h ├── config ├── libudis86 ├── udis86.h ├── syn.h ├── udint.h ├── extern.h ├── decode.h ├── syn-att.c ├── syn.c ├── syn-intel.c ├── types.h ├── itab.h ├── udis86.c └── decode.c ├── License ├── README.md └── Makefile /ooops_levels.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TACC/ooops/HEAD/ooops_levels.png -------------------------------------------------------------------------------- /change_io_on_fly.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TACC/ooops/HEAD/change_io_on_fly.jpg -------------------------------------------------------------------------------- /cal_threshhold.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ratio=0.95 4 | cat $1 | awk '{print $2}' | sort -n > 1 5 | nline=`wc -l 1 | awk '{print $1}'` 6 | npicked=`echo "$nline * $ratio / 1" | bc` 7 | head -n $npicked 1 | tail -n 1 8 | -------------------------------------------------------------------------------- /src/msleep.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char *argv[]) 5 | { 6 | int nMillSecond=100; 7 | struct timespec tim1, tim2; 8 | 9 | if(argc == 2) { 10 | nMillSecond = atoi(argv[1]); 11 | } 12 | tim1.tv_sec = nMillSecond / 1000; 13 | tim1.tv_nsec = (nMillSecond % 1000)*1000000; 14 | nanosleep(&tim1 , &tim2); 15 | 16 | return 0; 17 | } 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/test_open.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main(int argc, char *argv[]) 10 | { 11 | int i, nfile, fd; 12 | struct stat file_stat; 13 | 14 | nfile = atoi(argv[2]); 15 | for(i=0; i 0) close(fd); 18 | } 19 | 20 | return 0; 21 | } 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/test_stat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | int i, nfile; 13 | struct stat file_stat; 14 | 15 | lstat(argv[1], &file_stat); 16 | nfile = atoi(argv[2]); 17 | for(i=0; i 2 | #include 3 | #include /* for strncpy */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | static char szNICName[64]="ib0"; 13 | 14 | int main(int argc, char *argv[]) 15 | { 16 | int fd; 17 | struct ifreq ifr; 18 | 19 | fd = socket(AF_INET, SOCK_DGRAM, 0); 20 | /* I want to get an IPv4 IP address */ 21 | ifr.ifr_addr.sa_family = AF_INET; 22 | /* I want IP address attached to "eth0" */ 23 | if(argc == 2) strncpy(ifr.ifr_name, argv[1], strlen(argv[1])+1); 24 | else strncpy(ifr.ifr_name, "ib0", 4); 25 | ioctl(fd, SIOCGIFADDR, &ifr); 26 | close(fd); 27 | 28 | /* display result */ 29 | printf("%s\n", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr)); 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /include/dict.h: -------------------------------------------------------------------------------- 1 | #define MAX_NAME_LEN (16) 2 | #define INITIAL_SIZE (1024*32) 3 | 4 | struct elt { 5 | int next; // 6 | int value; 7 | char key[MAX_NAME_LEN]; 8 | }; 9 | 10 | struct dict { 11 | int size; /* size of the pointer table */ 12 | int n; /* number of elements stored */ 13 | int first_av; 14 | }; 15 | 16 | typedef struct dict *Dict; 17 | 18 | void DictCreate(Dict d, int nSize, struct elt ** p_elt_list, int ** p_ht_table); 19 | int DictInsertAuto(Dict d, const char *key, struct elt ** p_elt_list, int ** p_ht_table); 20 | int DictInsert(Dict d, const char *key, const int value, struct elt ** p_elt_list, int ** p_ht_table); 21 | int DictSearch(Dict d, const char *key, struct elt ** p_elt_list, int ** p_ht_table, unsigned long long *fn_hash); 22 | void DictDelete(Dict d, const char *key, struct elt ** p_elt_list, int ** p_ht_table); 23 | 24 | -------------------------------------------------------------------------------- /config: -------------------------------------------------------------------------------- 1 | 2 | 3 | FILE_SYS_TAG_0 /scratch 4 | T_THRESHOLD_OPEN_0 467.97 5 | MAX_OPEN_FREQ_0 1000 6 | T_THRESHOLD_LXSTAT_0 247.37 7 | MAX_STAT_FREQ_0 2000 8 | 9 | FILE_SYS_TAG_1 /work 10 | T_THRESHOLD_OPEN_1 907.14 11 | MAX_OPEN_FREQ_1 500 12 | T_THRESHOLD_LXSTAT_1 481.52 13 | MAX_STAT_FREQ_1 1000 14 | 15 | FILE_SYS_TAG_2 /home 16 | T_THRESHOLD_OPEN_2 317.94 17 | MAX_OPEN_FREQ_2 1500 18 | T_THRESHOLD_LXSTAT_2 205.43 19 | MAX_STAT_FREQ_2 2500 20 | 21 | 22 | 23 | 24 | 25 | 26 | FILE_SYS_TAG_0 /scratch 27 | T_THRESHOLD_OPEN_0 1198.67 28 | MAX_OPEN_FREQ_0 500 29 | T_THRESHOLD_LXSTAT_0 821.79 30 | MAX_STAT_FREQ_0 800 31 | 32 | FILE_SYS_TAG_1 /work 33 | T_THRESHOLD_OPEN_1 1948.61 34 | MAX_OPEN_FREQ_1 300 35 | T_THRESHOLD_LXSTAT_1 1206.11 36 | MAX_STAT_FREQ_1 500 37 | 38 | FILE_SYS_TAG_2 /home 39 | T_THRESHOLD_OPEN_2 1248.75 40 | MAX_OPEN_FREQ_2 400 41 | T_THRESHOLD_LXSTAT_2 731.82 42 | MAX_STAT_FREQ_2 700 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /include/hook.h: -------------------------------------------------------------------------------- 1 | #ifndef __HOOK 2 | #define __HOOK 3 | 4 | enum ERROR_CODE_REGISTER_HOOK{REGISTER_SUCCESS, REGISTER_NOT_FOUND_LIBC, REGISTER_DLOPEN_FAILED, \ 5 | REGISTER_MODULE_NAME_TOO_LONG, REGISTER_FUNC_NAME_TOO_LONG, REGISTER_TOO_MANY_HOOKS }; 6 | 7 | /* 8 | * register_a_hook - Add one target function into the list of the functions to intercept. 9 | * @module_name: The name of shared library. Both short name ("ld") and full name ("ld-2.17.so") are accepted. 10 | * @func_Name: The function name. 11 | * @new_func_addr: The address of our new implementation. 12 | * @ptr_org_func: *ptr_org_func will hold the address of orginal function implemented in lib module_name. 13 | * Returns: 14 | * 0: success; otherwise fail. 15 | */ 16 | int register_a_hook(const char *module_name, const char *func_Name, const void *new_func_addr, const long int *ptr_org_func); 17 | 18 | /* 19 | * install_hook - Install hooks by setting up trampolines for all functions registered. 20 | * Returns: 21 | * The number of hooks actually installed. 22 | */ 23 | int install_hook(void); 24 | 25 | /* 26 | * uninstall_hook - Uninstall hooks by cleaning up trampolines. 27 | * Returns: 28 | * void 29 | */ 30 | void uninstall_hook(void); 31 | 32 | #endif 33 | 34 | -------------------------------------------------------------------------------- /libudis86/udis86.h: -------------------------------------------------------------------------------- 1 | /* udis86 - udis86.h 2 | * 3 | * Copyright (c) 2002-2009 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #ifndef UDIS86_H 27 | #define UDIS86_H 28 | 29 | #include "types.h" 30 | #include "extern.h" 31 | #include "itab.h" 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /include/udis86.h: -------------------------------------------------------------------------------- 1 | /* udis86 - udis86.h 2 | * 3 | * Copyright (c) 2002-2009 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #ifndef UDIS86_H 27 | #define UDIS86_H 28 | 29 | #include "../libudis86/types.h" 30 | #include "../libudis86/extern.h" 31 | #include "../libudis86/itab.h" 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /License: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | -------------------------------------------------------------------------- 3 | -- ooops License 4 | -------------------------------------------------------------------------- 5 | -- 6 | -- ooops is licensed under the terms of the MIT license reproduced below 7 | -- This means that ooops is free software and can be used for both 8 | -- academic and commercial purposes at absolutely no cost. 9 | -- 10 | -- ---------------------------------------------------------------------- 11 | -- 12 | -- Copyright (C) 2017-2019 Lei Huang 13 | -- 14 | -- Permission is hereby granted, free of charge, to any person obtaining 15 | -- a copy of this software and associated documentation files (the 16 | -- "Software"), to deal in the Software without restriction, including 17 | -- without limitation the rights to use, copy, modify, merge, publish, 18 | -- distribute, sublicense, and/or sell copies of the Software, and to 19 | -- permit persons to whom the Software is furnished to do so, subject 20 | -- to the following conditions: 21 | -- 22 | -- The above copyright notice and this permission notice shall be 23 | -- included in all copies or substantial portions of the Software. 24 | -- 25 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 27 | -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | -- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29 | -- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30 | -- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31 | -- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 32 | -- THE SOFTWARE. 33 | -- 34 | -------------------------------------------------------------------------- 35 | *************************************************************************/ 36 | -------------------------------------------------------------------------------- /libudis86/syn.h: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/syn.h 2 | * 3 | * Copyright (c) 2002-2009 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #ifndef UD_SYN_H 27 | #define UD_SYN_H 28 | 29 | #include "types.h" 30 | #ifndef __UD_STANDALONE__ 31 | # include 32 | #endif /* __UD_STANDALONE__ */ 33 | 34 | extern const char* ud_reg_tab[]; 35 | 36 | uint64_t ud_syn_rel_target(struct ud*, struct ud_operand*); 37 | 38 | #ifdef __GNUC__ 39 | int ud_asmprintf(struct ud *u, const char *fmt, ...) 40 | __attribute__ ((format (printf, 2, 3))); 41 | #else 42 | int ud_asmprintf(struct ud *u, const char *fmt, ...); 43 | #endif 44 | 45 | void ud_syn_print_addr(struct ud *u, uint64_t addr); 46 | void ud_syn_print_imm(struct ud* u, const struct ud_operand *op); 47 | void ud_syn_print_mem_disp(struct ud* u, const struct ud_operand *, int sign); 48 | 49 | #endif /* UD_SYN_H */ 50 | 51 | /* 52 | vim: set ts=2 sw=2 expandtab 53 | */ 54 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ooops 2 | OOOPS, short for Optimal Overloaded IO Protection System, is an innovative IO workload managing system that optimally throttles the IO workload from the users' side. Thank Si Liu for coming up the name of this tool!

3 | Please feel free to contact [Lei Huang](https://www.tacc.utexas.edu/about/directory/lei-huang) for questions or suggestions. Thank you! 4 | 5 | Centralized file system shared by large number of users has been a week point of modern super computers for a while since there is no IO resource provisioning enforced. A small number of nodes could satuate the whole file system easily. Overloading file system could result in global filesystem performance degradation and even unresponsiveness for all users. ooops is designed to proactively protect file system and throttle the nodes with excessive I/O. With some modification, ooops can support user IO resource provisioning to enforce fair sharing. ooops is running on every node, so it can scale up to any arbitrary size of super computers. There is NO need for users to change anything on their side. The work for administrator to deploy ooops is also trivial. 6 | 7 | To compile,
8 | `make all`
9 | 10 | To measure the time needed for open() and stat() function calls on your file system
11 | Usage:
12 | `./t_open_stat fs_path n_hours`
13 | `./cal_threshhold.sh t_log_open.txt`
14 | `./cal_threshhold.sh t_log_stat.txt`
15 | Update config with the parameter you get for T_THRESHOLD_OPEN_x and T_THRESHOLD_LXSTAT_x. 16 | 17 | To deploy ooops,
18 | `export IO_LIMIT_CONFIG=${PWD}/config`
19 | `export LD_PRELOAD=${PWD}/wrapper.so`
20 | Run your apps as usual. 21 | 22 | To modify configurations, you can either change config or dynamically change the setting only on given nodes with set_io_param. Dynamically throttling with set_io_param works well without interrupting users' applications. 23 | `set_io_param server_idx t_open max_open_freq t_stat max_stat_freq`
24 | `or`
25 | `set_io_param server_idx [ low / medium / high / unlimit ]` 26 | 27 | Example to use ooops to control the level of IO from one compute node.
28 | ![Alt text](ooops_levels.png?raw=true "IO under various settings") 29 | 30 | Example to use ooops to adjust the level of IO on-fly when a job is running. 31 | ![Alt text](change_io_on_fly.jpg?raw=true "Adjust IO level on-fly") 32 | 33 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS_O=-O2 3 | CFLAGS=-Wall -Wextra -fPIC -O2 -I./include 4 | LFLAGS=-fPIC -shared -O2 -ldl -lrt 5 | OBJS=obj/ooops.o obj/hook.o obj/decode.o obj/itab.o obj/syn-att.o obj/syn-intel.o obj/syn.o obj/udis86.o 6 | HEADERS=include/udis86.h libudis86/decode.h libudis86/extern.h libudis86/itab.h libudis86/syn.h libudis86/types.h libudis86/udint.h src/hook_int.h 7 | RM=rm -rf 8 | 9 | # in cmd of windows 10 | ifeq ($(SHELL),sh.exe) 11 | RM := del /f/q 12 | endif 13 | 14 | #all: ooops.so get_ip mpi_aggregator msleep ooops ooopsd set_io_param 15 | all: ooops.so get_ip msleep ooops ooopsd set_io_param test_open test_stat t_open_stat 16 | 17 | ooops.so: ooops.o hook.o decode.o itab.o syn-att.o syn-intel.o syn.o udis86.o 18 | $(CC) $(LFLAGS) -o ooops.so obj/ooops.o obj/hook.o obj/decode.o obj/itab.o obj/syn-att.o obj/syn-intel.o obj/syn.o obj/udis86.o 19 | 20 | ooops.o: src/ooops.c $(HEADERS) 21 | $(CC) $(CFLAGS) -c -o obj/ooops.o $< 22 | 23 | hook.o: src/hook.c $(HEADERS) 24 | $(CC) $(CFLAGS) -c -o obj/hook.o $< 25 | 26 | decode.o: libudis86/decode.c $(HEADERS) 27 | $(CC) $(CFLAGS) -c -o obj/decode.o $< 28 | 29 | itab.o: libudis86/itab.c $(HEADERS) 30 | $(CC) $(CFLAGS) -c -o obj/itab.o $< 31 | 32 | syn-att.o: libudis86/syn-att.c $(HEADERS) 33 | $(CC) $(CFLAGS) -c -o obj/syn-att.o $< 34 | 35 | syn-intel.o: libudis86/syn-intel.c $(HEADERS) 36 | $(CC) $(CFLAGS) -c -o obj/syn-intel.o $< 37 | 38 | syn.o: libudis86/syn.c $(HEADERS) 39 | $(CC) $(CFLAGS) -c -o obj/syn.o $< 40 | 41 | udis86.o: libudis86/udis86.c $(HEADERS) 42 | $(CC) $(CFLAGS) -c -o obj/udis86.o $< 43 | get_ip: 44 | $(CC) $(CFLAGS_O) -o get_ip src/get_ip.c 45 | 46 | mpi_aggregator: 47 | mpicc -O2 -o mpi_aggregator src/mpi_aggregator.c 48 | 49 | msleep: 50 | $(CC) $(CFLAGS_O) -o msleep src/msleep.c 51 | 52 | ooops: 53 | $(CC) $(CFLAGS_O) -o ooops src/client.c -lrt -Iinclude 54 | 55 | ooopsd: 56 | $(CC) $(CFLAGS_O) -o ooopsd src/server.c src/dict.c src/xxhash.c -lrt -Iinclude 57 | 58 | set_io_param: 59 | $(CC) $(CFLAGS_O) -o set_io_param src/set_io_param.c -lrt 60 | 61 | t_open_stat: 62 | gcc -O2 -o t_open_stat src/t_open_stat.c 63 | chmod u+x cal_threshhold.sh 64 | 65 | test_open: 66 | gcc -O2 -o test_open src/test_open.c 67 | 68 | test_stat: 69 | gcc -O2 -o test_stat src/test_stat.c 70 | 71 | clean: 72 | $(RM) obj/*.o myopen.so get_ip msleep ooops ooopsd set_io_param test_open test_stat t_open_stat 73 | 74 | 75 | $(shell mkdir -p obj) 76 | -------------------------------------------------------------------------------- /libudis86/udint.h: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/udint.h -- definitions for internal use only 2 | * 3 | * Copyright (c) 2002-2009 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #ifndef _UDINT_H_ 27 | #define _UDINT_H_ 28 | 29 | #ifdef HAVE_CONFIG_H 30 | # include 31 | #endif /* HAVE_CONFIG_H */ 32 | 33 | #if defined(UD_DEBUG) && HAVE_ASSERT_H 34 | # include 35 | # define UD_ASSERT(_x) assert(_x) 36 | #else 37 | # define UD_ASSERT(_x) 38 | #endif /* !HAVE_ASSERT_H */ 39 | 40 | #if defined(UD_DEBUG) 41 | #define UDERR(u, msg) \ 42 | do { \ 43 | (u)->error = 1; \ 44 | fprintf(stderr, "decode-error: %s:%d: %s", \ 45 | __FILE__, __LINE__, (msg)); \ 46 | } while (0) 47 | #else 48 | #define UDERR(u, m) \ 49 | do { \ 50 | (u)->error = 1; \ 51 | } while (0) 52 | #endif /* !LOGERR */ 53 | 54 | #define UD_RETURN_ON_ERROR(u) \ 55 | do { \ 56 | if ((u)->error != 0) { \ 57 | return (u)->error; \ 58 | } \ 59 | } while (0) 60 | 61 | #define UD_RETURN_WITH_ERROR(u, m) \ 62 | do { \ 63 | UDERR(u, m); \ 64 | return (u)->error; \ 65 | } while (0) 66 | 67 | #ifndef __UD_STANDALONE__ 68 | # define UD_NON_STANDALONE(x) x 69 | #else 70 | # define UD_NON_STANDALONE(x) 71 | #endif 72 | 73 | /* printf formatting int64 specifier */ 74 | #ifdef FMT64 75 | # undef FMT64 76 | #endif 77 | #if defined(_MSC_VER) || defined(__BORLANDC__) 78 | # define FMT64 "I64" 79 | #else 80 | # if defined(__APPLE__) 81 | # define FMT64 "ll" 82 | # elif defined(__amd64__) || defined(__x86_64__) 83 | # define FMT64 "l" 84 | # else 85 | # define FMT64 "ll" 86 | # endif /* !x64 */ 87 | #endif 88 | 89 | #endif /* _UDINT_H_ */ 90 | -------------------------------------------------------------------------------- /src/client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define PORT 8888 14 | #define MAXLINE 1024 15 | #define T_INTERVAL_REPORT (5) 16 | 17 | #define MAX_FS_SERVER (8) // max number of distinct file system server to be tracked. 18 | #define MAX_REC (512) // number of record of file IO API call time stampe 19 | #define MAX_LEN_FS_NAME (16) 20 | #define DATA_TAG (0x41544144) 21 | 22 | static int T_Interal_Report=T_INTERVAL_REPORT; 23 | 24 | static char szTag_NodeName[]="From: "; 25 | 26 | void Get_BaseName(char szHostName[]); 27 | 28 | void Get_BaseName(char szHostName[]) 29 | { 30 | int i=0; 31 | while(szHostName[i] != 0) { 32 | if(szHostName[i] == '.') { 33 | szHostName[i] = 0; // truncate hostname[] 34 | return; 35 | } 36 | i++; 37 | } 38 | } 39 | 40 | // Data packet: 41 | // 1) char "DATA" 42 | // 2) rank "" 43 | // 3) data 44 | 45 | typedef struct { 46 | int Tag; 47 | int rank; 48 | long int Counter[MAX_FS_SERVER*4]; // data buff 49 | }OOOPSDATA, *POOOPSDATA; 50 | 51 | int main(int argc, char *argv[]) 52 | { 53 | int sockfd, nBytes_Written, nBytes_Read, rank; 54 | char szHostName[255], szFirstMsg[128], *szEnvT_Interval_Report; 55 | struct sockaddr_in servaddr; 56 | OOOPSDATA data; 57 | 58 | char mutex_name[64]; 59 | int nSize_Shared_Data, size_pt_mutex_t, shm_fd, uid; 60 | void *p_shm=NULL; // ptr to shared memory 61 | void *p_Data; 62 | 63 | szEnvT_Interval_Report = getenv("OOOPS_REPORT_T_INTERVAL"); 64 | if(szEnvT_Interval_Report != NULL) { 65 | T_Interal_Report = atoi(szEnvT_Interval_Report); 66 | } 67 | 68 | if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 69 | printf("socket creation failed"); 70 | exit(0); 71 | } 72 | 73 | gethostname(szHostName, 255); 74 | Get_BaseName(szHostName); 75 | 76 | memset(&servaddr, 0, sizeof(servaddr)); 77 | 78 | servaddr.sin_family = AF_INET; 79 | servaddr.sin_port = htons(PORT); 80 | servaddr.sin_addr.s_addr = inet_addr(argv[1]); 81 | 82 | if (connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) { 83 | printf("\n Error : Connect Failed \n"); 84 | } 85 | 86 | sprintf(szFirstMsg, "%s%s", szTag_NodeName, szHostName); 87 | nBytes_Written = write(sockfd, szFirstMsg, strlen(szFirstMsg)); 88 | nBytes_Read = read(sockfd, &rank, sizeof(int)); 89 | if(nBytes_Read == sizeof(int)) { 90 | // printf("Rank = %d\n", rank); 91 | } 92 | else { 93 | printf("Unexpected: %d\n", rank); 94 | } 95 | 96 | 97 | uid = getuid(); // ~ 10 us 98 | size_pt_mutex_t = sizeof(pthread_mutex_t); 99 | sprintf(mutex_name, "/my_mutex_%d", uid); 100 | nSize_Shared_Data = size_pt_mutex_t*2 + 8*MAX_FS_SERVER*4 + sizeof(uint64_t)*MAX_REC*MAX_FS_SERVER * 2; 101 | shm_fd = shm_open(mutex_name, O_RDWR, 0664); 102 | 103 | if(shm_fd < 0) { // failed 104 | perror("mpi_aggregator. main. shm_open. "); 105 | } 106 | p_shm = mmap(NULL, nSize_Shared_Data, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); 107 | if (p_shm == MAP_FAILED) { 108 | perror("mmap"); 109 | } 110 | p_Data = p_shm + size_pt_mutex_t*2; 111 | 112 | data.Tag = DATA_TAG; 113 | data.rank = rank; 114 | 115 | while(1) { 116 | memcpy(data.Counter, p_Data, sizeof(long int)*MAX_FS_SERVER*4); 117 | nBytes_Written = write(sockfd, &data, sizeof(OOOPSDATA)); 118 | sleep(T_Interal_Report); 119 | } 120 | 121 | sleep(1); 122 | close(sockfd); 123 | } 124 | -------------------------------------------------------------------------------- /libudis86/extern.h: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/extern.h 2 | * 3 | * Copyright (c) 2002-2009, 2013 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #ifndef UD_EXTERN_H 27 | #define UD_EXTERN_H 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | #include "types.h" 34 | 35 | /* ============================= PUBLIC API ================================= */ 36 | 37 | extern void ud_init(struct ud*); 38 | 39 | extern void ud_set_mode(struct ud*, uint8_t); 40 | 41 | extern void ud_set_pc(struct ud*, uint64_t); 42 | 43 | extern void ud_set_input_hook(struct ud*, int (*)(struct ud*)); 44 | 45 | extern void ud_set_input_buffer(struct ud*, const uint8_t*, size_t); 46 | 47 | #ifndef __UD_STANDALONE__ 48 | extern void ud_set_input_file(struct ud*, FILE*); 49 | #endif /* __UD_STANDALONE__ */ 50 | 51 | extern void ud_set_vendor(struct ud*, unsigned); 52 | 53 | extern void ud_set_syntax(struct ud*, void (*)(struct ud*)); 54 | 55 | extern void ud_input_skip(struct ud*, size_t); 56 | 57 | extern int ud_input_end(const struct ud*); 58 | 59 | extern unsigned int ud_decode(struct ud*); 60 | 61 | extern unsigned int ud_disassemble(struct ud*); 62 | 63 | extern void ud_translate_intel(struct ud*); 64 | 65 | extern void ud_translate_att(struct ud*); 66 | 67 | extern const char* ud_insn_asm(const struct ud* u); 68 | 69 | extern const uint8_t* ud_insn_ptr(const struct ud* u); 70 | 71 | extern uint64_t ud_insn_off(const struct ud*); 72 | 73 | extern const char* ud_insn_hex(struct ud*); 74 | 75 | extern unsigned int ud_insn_len(const struct ud* u); 76 | 77 | extern const struct ud_operand* ud_insn_opr(const struct ud *u, unsigned int n); 78 | 79 | extern int ud_opr_is_sreg(const struct ud_operand *opr); 80 | 81 | extern int ud_opr_is_gpr(const struct ud_operand *opr); 82 | 83 | extern enum ud_mnemonic_code ud_insn_mnemonic(const struct ud *u); 84 | 85 | extern const char* ud_lookup_mnemonic(enum ud_mnemonic_code c); 86 | 87 | extern void ud_set_user_opaque_data(struct ud*, void*); 88 | 89 | extern void* ud_get_user_opaque_data(const struct ud*); 90 | 91 | extern uint64_t ud_insn_sext_imm(const struct ud*, const struct ud_operand*); 92 | 93 | extern void ud_set_asm_buffer(struct ud *u, char *buf, size_t size); 94 | 95 | extern void ud_set_sym_resolver(struct ud *u, 96 | const char* (*resolver)(struct ud*, 97 | uint64_t addr, 98 | int64_t *offset)); 99 | 100 | /* ========================================================================== */ 101 | 102 | #ifdef __cplusplus 103 | } 104 | #endif 105 | #endif /* UD_EXTERN_H */ 106 | -------------------------------------------------------------------------------- /src/mpi_aggregator.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | //#include 10 | #include 11 | 12 | #define MAX_FS_SERVER (8) // max number of distinct file system server to be tracked. 13 | #define MAX_REC (512) // number of record of file IO API call time stampe 14 | #define MAX_LEN_FS_NAME (16) 15 | 16 | /* 17 | void msleep(void) 18 | { 19 | int nMillSecond=100; 20 | struct timespec tim1, tim2; 21 | 22 | tim1.tv_sec = 0; 23 | tim1.tv_nsec = 200*1000000; 24 | nanosleep(&tim1 , &tim2); 25 | } 26 | */ 27 | int main(int argc, char** argv) { 28 | int gsize; 29 | int rank; 30 | char mutex_name[64]; 31 | int nSize_Shared_Data, nSize_Shared_Param_Data, size_pt_mutex_t, shm_fd, shm_param_fd, uid; 32 | int i; 33 | void *p_shm=NULL, *p_param_shm=NULL; // ptr to shared memory 34 | int *p_open_Count[MAX_FS_SERVER]; 35 | int *p_lxstat_Count[MAX_FS_SERVER]; 36 | int *p_open_Delayed_Count[MAX_FS_SERVER]; 37 | int *p_lxstat_Delayed_Count[MAX_FS_SERVER]; 38 | char *p_FS_Tag_List[MAX_FS_SERVER]; // 16 bytes per record 39 | long int *p_Data=NULL; 40 | struct stat file_stat; 41 | 42 | MPI_Init(NULL, NULL); 43 | MPI_Comm_size(MPI_COMM_WORLD, &gsize); 44 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 45 | 46 | // msleep(); // sleep 0.15 second. 47 | 48 | uid = getuid(); // ~ 10 us 49 | size_pt_mutex_t = sizeof(pthread_mutex_t); 50 | sprintf(mutex_name, "/my_mutex_%d", uid); 51 | 52 | nSize_Shared_Data = size_pt_mutex_t*2 + 8*MAX_FS_SERVER*4 + sizeof(uint64_t)*MAX_REC*MAX_FS_SERVER * 2; 53 | 54 | shm_fd = shm_open(mutex_name, O_RDWR, 0664); 55 | 56 | if(shm_fd < 0) { // failed 57 | perror("mpi_aggregator. main. shm_open. "); 58 | } 59 | 60 | // Map mutex into the shared memory. 61 | p_shm = mmap(NULL, nSize_Shared_Data, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); 62 | if (p_shm == MAP_FAILED) { 63 | perror("mmap"); 64 | } 65 | 66 | 67 | sprintf(mutex_name, "/my_io_param_%d", uid); 68 | nSize_Shared_Param_Data = sizeof(uint64_t)*(MAX_FS_SERVER * 4 + 2 + 1) + (MAX_LEN_FS_NAME + sizeof(int))*MAX_FS_SERVER; 69 | shm_param_fd = shm_open(mutex_name, O_RDWR, 0664); 70 | 71 | if(shm_param_fd < 0) { // failed 72 | perror("mpi_aggregator. main. shm_open. shm_param_fd."); 73 | } 74 | 75 | p_param_shm = mmap(NULL, nSize_Shared_Param_Data, PROT_READ | PROT_WRITE, MAP_SHARED, shm_param_fd, 0); 76 | if (p_param_shm == MAP_FAILED) { 77 | perror("mmap"); 78 | } 79 | 80 | for(i=0; i 0) || (*(p_lxstat_Count[i]) > 0) ) { 91 | printf("Server %d: %s, Open_Count_Accum = %d Delayed_Open_Count_Accum = %d Stat_Count_Accum = %d Delayed_Stat_Count_Accum = %d\n", 92 | i, p_FS_Tag_List[i], *(p_open_Count[i]), *(p_open_Delayed_Count[i]), *(p_lxstat_Count[i]), *(p_lxstat_Delayed_Count[i])); 93 | } 94 | } 95 | */ 96 | p_Data = (long int *)malloc(8*MAX_FS_SERVER*4); 97 | memset(p_Data, 0, 8*MAX_FS_SERVER*4); 98 | MPI_Reduce(p_shm + size_pt_mutex_t*2, p_Data, MAX_FS_SERVER*4, MPI_LONG, MPI_SUM, 0, MPI_COMM_WORLD); 99 | 100 | if(rank == 0) { 101 | if(stat("/dev/shm/ooops/high_io", &file_stat) == 0) { // file exists. Print summary. 102 | for(i=0; i 0) || (*(p_lxstat_Count[i]) > 0) ) { 109 | // printf("Summary Server %d: %-8s, Open_Count_Accum = %d Delayed_Open_Count_Accum = %d Stat_Count_Accum = %d Delayed_Stat_Count_Accum = %d\n", 110 | // i, p_FS_Tag_List[i], *(p_open_Count[i]), *(p_open_Delayed_Count[i]), *(p_lxstat_Count[i]), *(p_lxstat_Delayed_Count[i])); 111 | printf("Summary Server %d: %-9s, %2d%% open is delayed. Open_Count_Accum = %6d Delayed_Open_Count_Accum = %6d \n %2d%% stat is delayed. Stat_Count_Accum = %6d Delayed_Stat_Count_Accum = %6d\n", 112 | i, p_FS_Tag_List[i], 100*(*(p_open_Delayed_Count[i]))/(*(p_open_Count[i])), *(p_open_Count[i]), *(p_open_Delayed_Count[i]), 113 | 100*(*(p_lxstat_Delayed_Count[i]))/(*(p_lxstat_Count[i])), *(p_lxstat_Count[i]), *(p_lxstat_Delayed_Count[i]) ); 114 | } 115 | } 116 | } 117 | 118 | } 119 | free(p_Data); 120 | 121 | munmap(p_shm, nSize_Shared_Data); 122 | munmap(p_param_shm, nSize_Shared_Param_Data); 123 | close(shm_fd); 124 | close(shm_param_fd); 125 | 126 | MPI_Finalize(); 127 | } 128 | -------------------------------------------------------------------------------- /src/t_open_stat.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | -------------------------------------------------------------------------- 3 | -- ooops License 4 | -------------------------------------------------------------------------- 5 | -- 6 | -- ooops is licensed under the terms of the MIT license reproduced below. 7 | -- This means that ooops is free software and can be used for both academic 8 | -- and commercial purposes at absolutely no cost. 9 | -- 10 | -- ---------------------------------------------------------------------- 11 | -- 12 | -- Copyright (C) 2018-2019 Lei Huang 13 | -- 14 | -- Permission is hereby granted, free of charge, to any person obtaining 15 | -- a copy of this software and associated documentation files (the 16 | -- "Software"), to deal in the Software without restriction, including 17 | -- without limitation the rights to use, copy, modify, merge, publish, 18 | -- distribute, sublicense, and/or sell copies of the Software, and to 19 | -- permit persons to whom the Software is furnished to do so, subject 20 | -- to the following conditions: 21 | -- 22 | -- The above copyright notice and this permission notice shall be 23 | -- included in all copies or substantial portions of the Software. 24 | -- 25 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 27 | -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | -- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29 | -- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30 | -- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31 | -- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 32 | -- THE SOFTWARE. 33 | -- 34 | -------------------------------------------------------------------------- 35 | *************************************************************************/ 36 | 37 | 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | 49 | char szDir[]="."; 50 | FILE *fOut_open; 51 | FILE *fOut_stat; 52 | uint64_t t_0; 53 | float freq; 54 | 55 | float Get_Freq(void); 56 | 57 | unsigned long int rdtscp(void) 58 | { 59 | unsigned long int rax, rdx; 60 | asm volatile ( "rdtscp\n" : "=a" (rax), "=d" (rdx) : : ); 61 | return (rdx << 32) + rax; 62 | } 63 | 64 | int nData=0; 65 | char szWorkDir[512]; 66 | 67 | int main(int argc, char *argv[]) 68 | { 69 | int fd, i; 70 | struct stat file_stat; 71 | int root_uid, user_uid; 72 | char szBuff[]="Hello World!", szOutBuff[64], szName[64]; 73 | struct timespec tim1, tim2; 74 | uint64_t t1, t2, t3, t4; 75 | double inv_freq, nHour; 76 | 77 | if(argc != 3) { 78 | printf("Usage: t_open_stat fs_path n_hours\nExample: t_open_stat /scratch/gropu/uid/test 24\n"); 79 | exit(1); 80 | } 81 | 82 | if( stat(argv[1], &file_stat) != 0 ) { 83 | printf("Error to get the stat of %s\nQuit\n", argv[1]); 84 | exit(1); 85 | } 86 | if( (file_stat.st_mode & S_IFMT) != S_IFDIR ) { 87 | printf("%s is NOT a directory.\nQuit\n", argv[1]); 88 | exit(1); 89 | } 90 | strcpy(szWorkDir, argv[1]); 91 | 92 | nHour = atof(argv[2]); 93 | 94 | tim1.tv_sec = 0; 95 | tim1.tv_nsec = 200000000; // sleep 0.2 second. Five files per second. 96 | nData = (int)(5*3600*nHour); 97 | 98 | fOut_open = fopen("t_log_open.txt", "w"); 99 | fOut_stat = fopen("t_log_stat.txt", "w"); 100 | 101 | freq = Get_Freq(); 102 | inv_freq = 1.0/freq; 103 | t_0 = rdtscp(); 104 | 105 | for(i=0; i> 0 ) & 1 ) 38 | #define P_rexb ( 1 << 1 ) 39 | #define P_REXB(n) ( ( n >> 1 ) & 1 ) 40 | #define P_inv64 ( 1 << 4 ) 41 | #define P_INV64(n) ( ( n >> 4 ) & 1 ) 42 | #define P_rexw ( 1 << 5 ) 43 | #define P_REXW(n) ( ( n >> 5 ) & 1 ) 44 | #define P_def64 ( 1 << 7 ) 45 | #define P_DEF64(n) ( ( n >> 7 ) & 1 ) 46 | #define P_rexr ( 1 << 8 ) 47 | #define P_REXR(n) ( ( n >> 8 ) & 1 ) 48 | #define P_oso ( 1 << 9 ) 49 | #define P_OSO(n) ( ( n >> 9 ) & 1 ) 50 | #define P_aso ( 1 << 10 ) 51 | #define P_ASO(n) ( ( n >> 10 ) & 1 ) 52 | #define P_rexx ( 1 << 11 ) 53 | #define P_REXX(n) ( ( n >> 11 ) & 1 ) 54 | #define P_ImpAddr ( 1 << 12 ) 55 | #define P_IMPADDR(n) ( ( n >> 12 ) & 1 ) 56 | #define P_seg ( 1 << 13 ) 57 | #define P_SEG(n) ( ( n >> 13 ) & 1 ) 58 | #define P_str ( 1 << 14 ) 59 | #define P_STR(n) ( ( n >> 14 ) & 1 ) 60 | #define P_strz ( 1 << 15 ) 61 | #define P_STR_ZF(n) ( ( n >> 15 ) & 1 ) 62 | 63 | /* operand type constants -- order is important! */ 64 | 65 | enum ud_operand_code { 66 | OP_NONE, 67 | 68 | OP_A, OP_E, OP_M, OP_G, 69 | OP_I, OP_F, 70 | 71 | OP_R0, OP_R1, OP_R2, OP_R3, 72 | OP_R4, OP_R5, OP_R6, OP_R7, 73 | 74 | OP_AL, OP_CL, OP_DL, 75 | OP_AX, OP_CX, OP_DX, 76 | OP_eAX, OP_eCX, OP_eDX, 77 | OP_rAX, OP_rCX, OP_rDX, 78 | 79 | OP_ES, OP_CS, OP_SS, OP_DS, 80 | OP_FS, OP_GS, 81 | 82 | OP_ST0, OP_ST1, OP_ST2, OP_ST3, 83 | OP_ST4, OP_ST5, OP_ST6, OP_ST7, 84 | 85 | OP_J, OP_S, OP_O, 86 | OP_I1, OP_I3, OP_sI, 87 | 88 | OP_V, OP_W, OP_Q, OP_P, 89 | OP_U, OP_N, OP_MU, 90 | 91 | OP_R, OP_C, OP_D, 92 | 93 | OP_MR 94 | } UD_ATTR_PACKED; 95 | 96 | 97 | /* operand size constants */ 98 | 99 | enum ud_operand_size { 100 | SZ_NA = 0, 101 | SZ_Z = 1, 102 | SZ_V = 2, 103 | SZ_RDQ = 7, 104 | 105 | /* the following values are used as is, 106 | * and thus hard-coded. changing them 107 | * will break internals 108 | */ 109 | SZ_B = 8, 110 | SZ_W = 16, 111 | SZ_D = 32, 112 | SZ_Q = 64, 113 | SZ_T = 80, 114 | SZ_O = 128, 115 | 116 | SZ_Y = 17, 117 | 118 | /* 119 | * complex size types, that encode sizes for operands 120 | * of type MR (memory or register), for internal use 121 | * only. Id space 256 and above. 122 | */ 123 | SZ_BD = (SZ_B << 8) | SZ_D, 124 | SZ_BV = (SZ_B << 8) | SZ_V, 125 | SZ_WD = (SZ_W << 8) | SZ_D, 126 | SZ_WV = (SZ_W << 8) | SZ_V, 127 | SZ_WY = (SZ_W << 8) | SZ_Y, 128 | SZ_DY = (SZ_D << 8) | SZ_Y, 129 | SZ_WO = (SZ_W << 8) | SZ_O, 130 | SZ_DO = (SZ_D << 8) | SZ_O, 131 | SZ_QO = (SZ_Q << 8) | SZ_O, 132 | 133 | } UD_ATTR_PACKED; 134 | 135 | 136 | /* resolve complex size type. 137 | */ 138 | static inline enum ud_operand_size 139 | Mx_mem_size(enum ud_operand_size size) 140 | { 141 | return (size >> 8) & 0xff; 142 | } 143 | 144 | static inline enum ud_operand_size 145 | Mx_reg_size(enum ud_operand_size size) 146 | { 147 | return size & 0xff; 148 | } 149 | 150 | /* A single operand of an entry in the instruction table. 151 | * (internal use only) 152 | */ 153 | struct ud_itab_entry_operand 154 | { 155 | enum ud_operand_code type; 156 | enum ud_operand_size size; 157 | }; 158 | 159 | 160 | /* A single entry in an instruction table. 161 | *(internal use only) 162 | */ 163 | struct ud_itab_entry 164 | { 165 | enum ud_mnemonic_code mnemonic; 166 | struct ud_itab_entry_operand operand1; 167 | struct ud_itab_entry_operand operand2; 168 | struct ud_itab_entry_operand operand3; 169 | uint32_t prefix; 170 | }; 171 | 172 | struct ud_lookup_table_list_entry { 173 | const uint16_t *table; 174 | enum ud_table_type type; 175 | const char *meta; 176 | }; 177 | 178 | 179 | 180 | static inline int 181 | ud_opcode_field_sext(uint8_t primary_opcode) 182 | { 183 | return (primary_opcode & 0x02) != 0; 184 | } 185 | 186 | extern struct ud_itab_entry ud_itab[]; 187 | extern struct ud_lookup_table_list_entry ud_lookup_table_list[]; 188 | 189 | #endif /* UD_DECODE_H */ 190 | 191 | /* vim:cindent 192 | * vim:expandtab 193 | * vim:ts=4 194 | * vim:sw=4 195 | */ 196 | -------------------------------------------------------------------------------- /src/dict.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "dict.h" 7 | #include "xxhash.h" 8 | 9 | #define GROWTH_FACTOR (2) 10 | #define MAX_LOAD_FACTOR (0.80) 11 | 12 | //int first_av; 13 | //struct elt elt_list[INITIAL_SIZE]; 14 | //struct elt *pelt_list[INITIAL_SIZE]; 15 | 16 | //struct dict *d=NULL; 17 | //struct elt *elt_list=NULL; 18 | //int *ht_table=NULL; 19 | 20 | // Totoal size = sizeof(dict) + sizeof(struct elt *)*INITIAL_SIZE + sizeof(struct elt)*INITIAL_SIZE 21 | // memory region three parts. 1) dict ( sizeof(dict) ) 2) pelt_list[] ( sizeof(struct elt *)*INITIAL_SIZE ) 3) elt_list ( sizeof(struct elt)*INITIAL_SIZE ) 22 | 23 | void Init_Pointers(Dict d, struct elt ** p_elt_list, int ** p_ht_table) 24 | { 25 | // ht_table = (int *)((void *)d + sizeof(struct dict)); 26 | // elt_list = (struct elt *)((void *)d + sizeof(struct dict) + sizeof(int)*(d->size)); 27 | *p_ht_table = (int *)((void *)d + sizeof(struct dict)); 28 | *p_elt_list = (struct elt *)((void *)d + sizeof(struct dict) + sizeof(int)*(d->size)); 29 | } 30 | 31 | void DictCreate(Dict d, int nSize, struct elt ** p_elt_list, int ** p_ht_table) 32 | { 33 | int i; 34 | 35 | if(d == NULL) { 36 | printf("d = NULL.\nThe memory for hash table is not allocated.\nQuit\n"); 37 | exit(1); 38 | } 39 | 40 | if(nSize) { 41 | if(nSize) { 42 | d->size = nSize; 43 | } 44 | else { 45 | d->size = INITIAL_SIZE; 46 | } 47 | d->n = 0; 48 | } 49 | Init_Pointers(d, p_elt_list, p_ht_table); 50 | 51 | // ht_table = (int *)((void *)d + sizeof(dict)); 52 | // elt_list = (struct elt *)((void *)d + sizeof(struct dict) + sizeof(int)*INITIAL_SIZE); 53 | 54 | if(nSize) { 55 | for(i = 0; i < d->size; i++) (*p_ht_table)[i] = -1; 56 | d->first_av = 0; 57 | for(i=0; isize; i++) { 58 | (*p_elt_list)[i].next = i+1; 59 | } 60 | (*p_elt_list)[d->size - 1].next = -1; // the end 61 | } 62 | } 63 | /* 64 | static void grow(Dict d) 65 | { 66 | Dict d2; // new dictionary we'll create 67 | struct dict swap; // temporary structure for brain transplant 68 | int i; 69 | struct elt *e; 70 | 71 | d2 = internalDictCreate(d->size * GROWTH_FACTOR); 72 | 73 | for(i = 0; i < d->size; i++) { 74 | for(e = d->table[i]; e != 0; e = e->next) { 75 | // note: this recopies everything 76 | // a more efficient implementation would 77 | // patch out the strdups inside DictInsert 78 | // to avoid this problem 79 | DictInsert(d2, e->key, e->value); 80 | } 81 | } 82 | 83 | // the hideous part 84 | // We'll swap the guts of d and d2 85 | // then call DictDestroy on d2 86 | swap = *d; 87 | *d = *d2; 88 | *d2 = swap; 89 | 90 | DictDestroy(d2); 91 | } 92 | */ 93 | 94 | // insert a new key-value pair into an existing dictionary 95 | int DictInsert(Dict d, const char *key, const int value, struct elt ** p_elt_list, int ** p_ht_table) 96 | { 97 | struct elt *e; 98 | unsigned long long h; 99 | int first_av_Save, nLen; 100 | 101 | assert(key); 102 | 103 | first_av_Save = d->first_av; 104 | e = &( (*p_elt_list)[d->first_av]); // first available unit 105 | strcpy(e->key, key); 106 | e->value = value; 107 | 108 | d->first_av = e->next; // pointing to the next available unit 109 | 110 | nLen = strlen(key); 111 | if(nLen >= MAX_NAME_LEN) { 112 | printf("ERROR in DictInsert: Hash table key length is not long enough. Overflowed.\n"); 113 | } 114 | h = XXH64(key, nLen, 0) % d->size; 115 | 116 | e->next = (*p_ht_table)[h]; 117 | (*p_ht_table)[h] = first_av_Save; 118 | d->n++; 119 | 120 | /* grow table if there is not enough room */ 121 | if(d->n >= (d->size * MAX_LOAD_FACTOR) ) { 122 | printf("Hash table is FULL.\nQuit.\n"); 123 | exit(1); 124 | // grow(d); 125 | } 126 | return first_av_Save; // the unit saving the data 127 | } 128 | 129 | int DictInsertAuto(Dict d, const char *key, struct elt ** p_elt_list, int ** p_ht_table) 130 | { 131 | struct elt *e; 132 | unsigned long long h; 133 | int first_av_Save; 134 | 135 | assert(key); 136 | 137 | first_av_Save = d->first_av; 138 | e = &( (*p_elt_list)[d->first_av]); // first available unit 139 | strcpy(e->key, key); 140 | e->value = first_av_Save; 141 | 142 | d->first_av = e->next; // pointing to the next available unit 143 | 144 | h = XXH64(key, strlen(key), 0) % d->size; 145 | 146 | e->next = (*p_ht_table)[h]; 147 | (*p_ht_table)[h] = first_av_Save; 148 | d->n++; 149 | 150 | /* grow table if there is not enough room */ 151 | if(d->n >= (d->size * MAX_LOAD_FACTOR) ) { 152 | printf("Hash table is FULL.\nQuit.\n"); 153 | exit(1); 154 | // grow(d); 155 | } 156 | return first_av_Save; // the unit saving the data 157 | } 158 | /* return the most recently inserted value associated with a key */ 159 | /* or 0 if no matching key is present */ 160 | int DictSearch(Dict d, const char *key, struct elt ** p_elt_list, int ** p_ht_table, unsigned long long *fn_hash) 161 | { 162 | int idx; 163 | struct elt *e; 164 | 165 | if(d->n == 0) return (-1); 166 | 167 | *fn_hash = XXH64(key, strlen(key), 0); 168 | idx = (*p_ht_table)[(*fn_hash)% d->size]; 169 | if(idx == -1) { 170 | return (-1); 171 | } 172 | 173 | e = &( (*p_elt_list)[idx] ); 174 | while(1) { 175 | if(!strcmp(e->key, key)) { 176 | return e->value; 177 | } 178 | else { 179 | idx = e->next; 180 | if(idx == -1) { // end 181 | return (-1); 182 | } 183 | e = &( (*p_elt_list)[idx] ); 184 | } 185 | } 186 | 187 | return -1; 188 | } 189 | 190 | 191 | // delete the most recently inserted record with the given key 192 | // if there is no such record, has no effect 193 | void DictDelete(Dict d, const char *key, struct elt ** p_elt_list, int ** p_ht_table) 194 | { 195 | int idx, next; 196 | unsigned long long h; 197 | 198 | h = XXH64(key, strlen(key), 0) % d->size; 199 | idx = (*p_ht_table)[h]; 200 | 201 | if(!strcmp((*p_elt_list)[idx].key, key)) { // found as the first element 202 | (*p_ht_table)[h] = (*p_elt_list)[idx].next; 203 | (*p_elt_list)[idx].next = d->first_av; 204 | d->first_av = idx; // put back as the beginning of the free space 205 | d->n--; 206 | return; 207 | } 208 | 209 | next = (*p_elt_list)[idx].next; 210 | for(; next != -1; next = (*p_elt_list)[idx].next) { 211 | if(!strcmp((*p_elt_list)[next].key, key)) { 212 | (*p_elt_list)[idx].next = (*p_elt_list)[next].next; 213 | (*p_elt_list)[next].next = d->first_av; 214 | d->first_av = next; 215 | d->n--; 216 | return; 217 | } 218 | idx = next; 219 | } 220 | } 221 | 222 | 223 | -------------------------------------------------------------------------------- /libudis86/syn-att.c: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/syn-att.c 2 | * 3 | * Copyright (c) 2002-2009 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #include "types.h" 27 | #include "extern.h" 28 | #include "decode.h" 29 | #include "itab.h" 30 | #include "syn.h" 31 | #include "udint.h" 32 | 33 | /* ----------------------------------------------------------------------------- 34 | * opr_cast() - Prints an operand cast. 35 | * ----------------------------------------------------------------------------- 36 | */ 37 | static void 38 | opr_cast(struct ud* u, struct ud_operand* op) 39 | { 40 | switch(op->size) { 41 | case 16 : case 32 : 42 | ud_asmprintf(u, "*"); break; 43 | default: break; 44 | } 45 | } 46 | 47 | /* ----------------------------------------------------------------------------- 48 | * gen_operand() - Generates assembly output for each operand. 49 | * ----------------------------------------------------------------------------- 50 | */ 51 | static void 52 | gen_operand(struct ud* u, struct ud_operand* op) 53 | { 54 | switch(op->type) { 55 | case UD_OP_CONST: 56 | ud_asmprintf(u, "$0x%x", op->lval.udword); 57 | break; 58 | 59 | case UD_OP_REG: 60 | ud_asmprintf(u, "%%%s", ud_reg_tab[op->base - UD_R_AL]); 61 | break; 62 | 63 | case UD_OP_MEM: 64 | if (u->br_far) { 65 | opr_cast(u, op); 66 | } 67 | if (u->pfx_seg) { 68 | ud_asmprintf(u, "%%%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]); 69 | } 70 | if (op->offset != 0) { 71 | ud_syn_print_mem_disp(u, op, 0); 72 | } 73 | if (op->base) { 74 | ud_asmprintf(u, "(%%%s", ud_reg_tab[op->base - UD_R_AL]); 75 | } 76 | if (op->index) { 77 | if (op->base) { 78 | ud_asmprintf(u, ","); 79 | } else { 80 | ud_asmprintf(u, "("); 81 | } 82 | ud_asmprintf(u, "%%%s", ud_reg_tab[op->index - UD_R_AL]); 83 | } 84 | if (op->scale) { 85 | ud_asmprintf(u, ",%d", op->scale); 86 | } 87 | if (op->base || op->index) { 88 | ud_asmprintf(u, ")"); 89 | } 90 | break; 91 | 92 | case UD_OP_IMM: 93 | ud_asmprintf(u, "$"); 94 | ud_syn_print_imm(u, op); 95 | break; 96 | 97 | case UD_OP_JIMM: 98 | ud_syn_print_addr(u, ud_syn_rel_target(u, op)); 99 | break; 100 | 101 | case UD_OP_PTR: 102 | switch (op->size) { 103 | case 32: 104 | ud_asmprintf(u, "$0x%x, $0x%x", op->lval.ptr.seg, 105 | op->lval.ptr.off & 0xFFFF); 106 | break; 107 | case 48: 108 | ud_asmprintf(u, "$0x%x, $0x%x", op->lval.ptr.seg, 109 | op->lval.ptr.off); 110 | break; 111 | } 112 | break; 113 | 114 | default: return; 115 | } 116 | } 117 | 118 | /* ============================================================================= 119 | * translates to AT&T syntax 120 | * ============================================================================= 121 | */ 122 | extern void 123 | ud_translate_att(struct ud *u) 124 | { 125 | int size = 0; 126 | int star = 0; 127 | 128 | /* check if P_OSO prefix is used */ 129 | if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) { 130 | switch (u->dis_mode) { 131 | case 16: 132 | ud_asmprintf(u, "o32 "); 133 | break; 134 | case 32: 135 | case 64: 136 | ud_asmprintf(u, "o16 "); 137 | break; 138 | } 139 | } 140 | 141 | /* check if P_ASO prefix was used */ 142 | if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) { 143 | switch (u->dis_mode) { 144 | case 16: 145 | ud_asmprintf(u, "a32 "); 146 | break; 147 | case 32: 148 | ud_asmprintf(u, "a16 "); 149 | break; 150 | case 64: 151 | ud_asmprintf(u, "a32 "); 152 | break; 153 | } 154 | } 155 | 156 | if (u->pfx_lock) 157 | ud_asmprintf(u, "lock "); 158 | if (u->pfx_rep) { 159 | ud_asmprintf(u, "rep "); 160 | } else if (u->pfx_rep) { 161 | ud_asmprintf(u, "repe "); 162 | } else if (u->pfx_repne) { 163 | ud_asmprintf(u, "repne "); 164 | } 165 | 166 | /* special instructions */ 167 | switch (u->mnemonic) { 168 | case UD_Iretf: 169 | ud_asmprintf(u, "lret "); 170 | break; 171 | case UD_Idb: 172 | ud_asmprintf(u, ".byte 0x%x", u->operand[0].lval.ubyte); 173 | return; 174 | case UD_Ijmp: 175 | case UD_Icall: 176 | if (u->br_far) ud_asmprintf(u, "l"); 177 | if (u->operand[0].type == UD_OP_REG) { 178 | star = 1; 179 | } 180 | ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic)); 181 | break; 182 | case UD_Ibound: 183 | case UD_Ienter: 184 | if (u->operand[0].type != UD_NONE) 185 | gen_operand(u, &u->operand[0]); 186 | if (u->operand[1].type != UD_NONE) { 187 | ud_asmprintf(u, ","); 188 | gen_operand(u, &u->operand[1]); 189 | } 190 | return; 191 | default: 192 | ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic)); 193 | } 194 | 195 | if (size == 8) 196 | ud_asmprintf(u, "b"); 197 | else if (size == 16) 198 | ud_asmprintf(u, "w"); 199 | else if (size == 64) 200 | ud_asmprintf(u, "q"); 201 | 202 | if (star) { 203 | ud_asmprintf(u, " *"); 204 | } else { 205 | ud_asmprintf(u, " "); 206 | } 207 | 208 | if (u->operand[2].type != UD_NONE) { 209 | gen_operand(u, &u->operand[2]); 210 | ud_asmprintf(u, ", "); 211 | } 212 | 213 | if (u->operand[1].type != UD_NONE) { 214 | gen_operand(u, &u->operand[1]); 215 | ud_asmprintf(u, ", "); 216 | } 217 | 218 | if (u->operand[0].type != UD_NONE) 219 | gen_operand(u, &u->operand[0]); 220 | } 221 | 222 | /* 223 | vim: set ts=2 sw=2 expandtab 224 | */ 225 | -------------------------------------------------------------------------------- /libudis86/syn.c: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/syn.c 2 | * 3 | * Copyright (c) 2002-2013 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #include "types.h" 27 | #include "decode.h" 28 | #include "syn.h" 29 | #include "udint.h" 30 | 31 | /* ----------------------------------------------------------------------------- 32 | * Intel Register Table - Order Matters (types.h)! 33 | * ----------------------------------------------------------------------------- 34 | */ 35 | const char* ud_reg_tab[] = 36 | { 37 | "al", "cl", "dl", "bl", 38 | "ah", "ch", "dh", "bh", 39 | "spl", "bpl", "sil", "dil", 40 | "r8b", "r9b", "r10b", "r11b", 41 | "r12b", "r13b", "r14b", "r15b", 42 | 43 | "ax", "cx", "dx", "bx", 44 | "sp", "bp", "si", "di", 45 | "r8w", "r9w", "r10w", "r11w", 46 | "r12w", "r13w" , "r14w", "r15w", 47 | 48 | "eax", "ecx", "edx", "ebx", 49 | "esp", "ebp", "esi", "edi", 50 | "r8d", "r9d", "r10d", "r11d", 51 | "r12d", "r13d", "r14d", "r15d", 52 | 53 | "rax", "rcx", "rdx", "rbx", 54 | "rsp", "rbp", "rsi", "rdi", 55 | "r8", "r9", "r10", "r11", 56 | "r12", "r13", "r14", "r15", 57 | 58 | "es", "cs", "ss", "ds", 59 | "fs", "gs", 60 | 61 | "cr0", "cr1", "cr2", "cr3", 62 | "cr4", "cr5", "cr6", "cr7", 63 | "cr8", "cr9", "cr10", "cr11", 64 | "cr12", "cr13", "cr14", "cr15", 65 | 66 | "dr0", "dr1", "dr2", "dr3", 67 | "dr4", "dr5", "dr6", "dr7", 68 | "dr8", "dr9", "dr10", "dr11", 69 | "dr12", "dr13", "dr14", "dr15", 70 | 71 | "mm0", "mm1", "mm2", "mm3", 72 | "mm4", "mm5", "mm6", "mm7", 73 | 74 | "st0", "st1", "st2", "st3", 75 | "st4", "st5", "st6", "st7", 76 | 77 | "xmm0", "xmm1", "xmm2", "xmm3", 78 | "xmm4", "xmm5", "xmm6", "xmm7", 79 | "xmm8", "xmm9", "xmm10", "xmm11", 80 | "xmm12", "xmm13", "xmm14", "xmm15", 81 | 82 | "rip" 83 | }; 84 | 85 | 86 | uint64_t 87 | ud_syn_rel_target(struct ud *u, struct ud_operand *opr) 88 | { 89 | const uint64_t trunc_mask = 0xffffffffffffffffull >> (64 - u->opr_mode); 90 | switch (opr->size) { 91 | case 8 : return (u->pc + opr->lval.sbyte) & trunc_mask; 92 | case 16: return (u->pc + opr->lval.sword) & trunc_mask; 93 | case 32: return (u->pc + opr->lval.sdword) & trunc_mask; 94 | default: UD_ASSERT(!"invalid relative offset size."); 95 | return 0ull; 96 | } 97 | } 98 | 99 | 100 | /* 101 | * asmprintf 102 | * Printf style function for printing translated assembly 103 | * output. Returns the number of characters written and 104 | * moves the buffer pointer forward. On an overflow, 105 | * returns a negative number and truncates the output. 106 | */ 107 | int 108 | ud_asmprintf(struct ud *u, const char *fmt, ...) 109 | { 110 | int ret; 111 | int avail; 112 | va_list ap; 113 | va_start(ap, fmt); 114 | avail = u->asm_buf_size - u->asm_buf_fill - 1 /* nullchar */; 115 | ret = vsnprintf((char*) u->asm_buf + u->asm_buf_fill, avail, fmt, ap); 116 | if (ret < 0 || ret > avail) { 117 | u->asm_buf_fill = u->asm_buf_size - 1; 118 | } else { 119 | u->asm_buf_fill += ret; 120 | } 121 | va_end(ap); 122 | return ret; 123 | } 124 | 125 | 126 | void 127 | ud_syn_print_addr(struct ud *u, uint64_t addr) 128 | { 129 | const char *name = NULL; 130 | if (u->sym_resolver) { 131 | int64_t offset = 0; 132 | name = u->sym_resolver(u, addr, &offset); 133 | if (name) { 134 | if (offset) { 135 | ud_asmprintf(u, "%s%+" FMT64 "d", name, offset); 136 | } else { 137 | ud_asmprintf(u, "%s", name); 138 | } 139 | return; 140 | } 141 | } 142 | ud_asmprintf(u, "0x%" FMT64 "x", addr); 143 | } 144 | 145 | 146 | void 147 | ud_syn_print_imm(struct ud* u, const struct ud_operand *op) 148 | { 149 | uint64_t v; 150 | if (op->_oprcode == OP_sI && op->size != u->opr_mode) { 151 | if (op->size == 8) { 152 | v = (int64_t)op->lval.sbyte; 153 | } else { 154 | UD_ASSERT(op->size == 32); 155 | v = (int64_t)op->lval.sdword; 156 | } 157 | if (u->opr_mode < 64) { 158 | v = v & ((1ull << u->opr_mode) - 1ull); 159 | } 160 | } else { 161 | switch (op->size) { 162 | case 8 : v = op->lval.ubyte; break; 163 | case 16: v = op->lval.uword; break; 164 | case 32: v = op->lval.udword; break; 165 | case 64: v = op->lval.uqword; break; 166 | default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */ 167 | } 168 | } 169 | ud_asmprintf(u, "0x%" FMT64 "x", v); 170 | } 171 | 172 | 173 | void 174 | ud_syn_print_mem_disp(struct ud* u, const struct ud_operand *op, int sign) 175 | { 176 | UD_ASSERT(op->offset != 0); 177 | if (op->base == UD_NONE && op->index == UD_NONE) { 178 | uint64_t v; 179 | UD_ASSERT(op->scale == UD_NONE && op->offset != 8); 180 | /* unsigned mem-offset */ 181 | switch (op->offset) { 182 | case 16: v = op->lval.uword; break; 183 | case 32: v = op->lval.udword; break; 184 | case 64: v = op->lval.uqword; break; 185 | default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */ 186 | } 187 | ud_asmprintf(u, "0x%" FMT64 "x", v); 188 | } else { 189 | int64_t v; 190 | UD_ASSERT(op->offset != 64); 191 | switch (op->offset) { 192 | case 8 : v = op->lval.sbyte; break; 193 | case 16: v = op->lval.sword; break; 194 | case 32: v = op->lval.sdword; break; 195 | default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */ 196 | } 197 | if (v < 0) { 198 | ud_asmprintf(u, "-0x%" FMT64 "x", -v); 199 | } else if (v > 0) { 200 | ud_asmprintf(u, "%s0x%" FMT64 "x", sign? "+" : "", v); 201 | } 202 | } 203 | } 204 | 205 | /* 206 | vim: set ts=2 sw=2 expandtab 207 | */ 208 | -------------------------------------------------------------------------------- /libudis86/syn-intel.c: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/syn-intel.c 2 | * 3 | * Copyright (c) 2002-2013 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #include "types.h" 27 | #include "extern.h" 28 | #include "decode.h" 29 | #include "itab.h" 30 | #include "syn.h" 31 | #include "udint.h" 32 | 33 | /* ----------------------------------------------------------------------------- 34 | * opr_cast() - Prints an operand cast. 35 | * ----------------------------------------------------------------------------- 36 | */ 37 | static void 38 | opr_cast(struct ud* u, struct ud_operand* op) 39 | { 40 | if (u->br_far) { 41 | ud_asmprintf(u, "far "); 42 | } 43 | switch(op->size) { 44 | case 8: ud_asmprintf(u, "byte " ); break; 45 | case 16: ud_asmprintf(u, "word " ); break; 46 | case 32: ud_asmprintf(u, "dword "); break; 47 | case 64: ud_asmprintf(u, "qword "); break; 48 | case 80: ud_asmprintf(u, "tword "); break; 49 | default: break; 50 | } 51 | } 52 | 53 | /* ----------------------------------------------------------------------------- 54 | * gen_operand() - Generates assembly output for each operand. 55 | * ----------------------------------------------------------------------------- 56 | */ 57 | static void gen_operand(struct ud* u, struct ud_operand* op, int syn_cast) 58 | { 59 | switch(op->type) { 60 | case UD_OP_REG: 61 | ud_asmprintf(u, "%s", ud_reg_tab[op->base - UD_R_AL]); 62 | break; 63 | 64 | case UD_OP_MEM: 65 | if (syn_cast) { 66 | opr_cast(u, op); 67 | } 68 | ud_asmprintf(u, "["); 69 | if (u->pfx_seg) { 70 | ud_asmprintf(u, "%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]); 71 | } 72 | if (op->base) { 73 | ud_asmprintf(u, "%s", ud_reg_tab[op->base - UD_R_AL]); 74 | } 75 | if (op->index) { 76 | ud_asmprintf(u, "%s%s", op->base != UD_NONE? "+" : "", 77 | ud_reg_tab[op->index - UD_R_AL]); 78 | if (op->scale) { 79 | ud_asmprintf(u, "*%d", op->scale); 80 | } 81 | } 82 | if (op->offset != 0) { 83 | ud_syn_print_mem_disp(u, op, (op->base != UD_NONE || 84 | op->index != UD_NONE) ? 1 : 0); 85 | } 86 | ud_asmprintf(u, "]"); 87 | break; 88 | 89 | case UD_OP_IMM: 90 | ud_syn_print_imm(u, op); 91 | break; 92 | 93 | 94 | case UD_OP_JIMM: 95 | ud_syn_print_addr(u, ud_syn_rel_target(u, op)); 96 | break; 97 | 98 | case UD_OP_PTR: 99 | switch (op->size) { 100 | case 32: 101 | ud_asmprintf(u, "word 0x%x:0x%x", op->lval.ptr.seg, 102 | op->lval.ptr.off & 0xFFFF); 103 | break; 104 | case 48: 105 | ud_asmprintf(u, "dword 0x%x:0x%x", op->lval.ptr.seg, 106 | op->lval.ptr.off); 107 | break; 108 | } 109 | break; 110 | 111 | case UD_OP_CONST: 112 | if (syn_cast) opr_cast(u, op); 113 | ud_asmprintf(u, "%d", op->lval.udword); 114 | break; 115 | 116 | default: return; 117 | } 118 | } 119 | 120 | /* ============================================================================= 121 | * translates to intel syntax 122 | * ============================================================================= 123 | */ 124 | extern void 125 | ud_translate_intel(struct ud* u) 126 | { 127 | /* check if P_OSO prefix is used */ 128 | if (!P_OSO(u->itab_entry->prefix) && u->pfx_opr) { 129 | switch (u->dis_mode) { 130 | case 16: ud_asmprintf(u, "o32 "); break; 131 | case 32: 132 | case 64: ud_asmprintf(u, "o16 "); break; 133 | } 134 | } 135 | 136 | /* check if P_ASO prefix was used */ 137 | if (!P_ASO(u->itab_entry->prefix) && u->pfx_adr) { 138 | switch (u->dis_mode) { 139 | case 16: ud_asmprintf(u, "a32 "); break; 140 | case 32: ud_asmprintf(u, "a16 "); break; 141 | case 64: ud_asmprintf(u, "a32 "); break; 142 | } 143 | } 144 | 145 | if (u->pfx_seg && 146 | u->operand[0].type != UD_OP_MEM && 147 | u->operand[1].type != UD_OP_MEM ) { 148 | ud_asmprintf(u, "%s ", ud_reg_tab[u->pfx_seg - UD_R_AL]); 149 | } 150 | 151 | if (u->pfx_lock) { 152 | ud_asmprintf(u, "lock "); 153 | } 154 | if (u->pfx_rep) { 155 | ud_asmprintf(u, "rep "); 156 | } else if (u->pfx_repe) { 157 | ud_asmprintf(u, "repe "); 158 | } else if (u->pfx_repne) { 159 | ud_asmprintf(u, "repne "); 160 | } 161 | 162 | /* print the instruction mnemonic */ 163 | ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic)); 164 | 165 | if (u->operand[0].type != UD_NONE) { 166 | int cast = 0; 167 | ud_asmprintf(u, " "); 168 | if (u->operand[0].type == UD_OP_MEM) { 169 | if (u->operand[1].type == UD_OP_IMM || 170 | u->operand[1].type == UD_OP_CONST || 171 | u->operand[1].type == UD_NONE || 172 | (u->operand[0].size != u->operand[1].size && 173 | u->operand[1].type != UD_OP_REG)) { 174 | cast = 1; 175 | } else if (u->operand[1].type == UD_OP_REG && 176 | u->operand[1].base == UD_R_CL) { 177 | switch (u->mnemonic) { 178 | case UD_Ircl: 179 | case UD_Irol: 180 | case UD_Iror: 181 | case UD_Ircr: 182 | case UD_Ishl: 183 | case UD_Ishr: 184 | case UD_Isar: 185 | cast = 1; 186 | break; 187 | default: break; 188 | } 189 | } 190 | } 191 | gen_operand(u, &u->operand[0], cast); 192 | } 193 | 194 | if (u->operand[1].type != UD_NONE) { 195 | int cast = 0; 196 | ud_asmprintf(u, ", "); 197 | if (u->operand[1].type == UD_OP_MEM && 198 | u->operand[0].size != u->operand[1].size && 199 | !ud_opr_is_sreg(&u->operand[0])) { 200 | cast = 1; 201 | } 202 | gen_operand(u, &u->operand[1], cast); 203 | } 204 | 205 | if (u->operand[2].type != UD_NONE) { 206 | ud_asmprintf(u, ", "); 207 | gen_operand(u, &u->operand[2], 0); 208 | } 209 | } 210 | 211 | /* 212 | vim: set ts=2 sw=2 expandtab 213 | */ 214 | -------------------------------------------------------------------------------- /libudis86/types.h: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/types.h 2 | * 3 | * Copyright (c) 2002-2013 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #ifndef UD_TYPES_H 27 | #define UD_TYPES_H 28 | 29 | #ifdef __KERNEL__ 30 | /* -D__KERNEL__ is automatically passed on the command line when 31 | building something as part of the Linux kernel */ 32 | # include 33 | # include 34 | # ifndef __UD_STANDALONE__ 35 | # define __UD_STANDALONE__ 1 36 | #endif 37 | #endif /* __KERNEL__ */ 38 | 39 | #if defined(_MSC_VER) || defined(__BORLANDC__) 40 | # include 41 | # include 42 | # define inline __inline /* MS Visual Studio requires __inline 43 | instead of inline for C code */ 44 | #elif !defined(__UD_STANDALONE__) 45 | # include 46 | # include 47 | #endif /* !__UD_STANDALONE__ */ 48 | 49 | /* gcc specific extensions */ 50 | #ifdef __GNUC__ 51 | # define UD_ATTR_PACKED __attribute__((packed)) 52 | #else 53 | # define UD_ATTR_PACKED 54 | #endif /* UD_ATTR_PACKED */ 55 | 56 | 57 | /* ----------------------------------------------------------------------------- 58 | * All possible "types" of objects in udis86. Order is Important! 59 | * ----------------------------------------------------------------------------- 60 | */ 61 | enum ud_type 62 | { 63 | UD_NONE, 64 | 65 | /* 8 bit GPRs */ 66 | UD_R_AL, UD_R_CL, UD_R_DL, UD_R_BL, 67 | UD_R_AH, UD_R_CH, UD_R_DH, UD_R_BH, 68 | UD_R_SPL, UD_R_BPL, UD_R_SIL, UD_R_DIL, 69 | UD_R_R8B, UD_R_R9B, UD_R_R10B, UD_R_R11B, 70 | UD_R_R12B, UD_R_R13B, UD_R_R14B, UD_R_R15B, 71 | 72 | /* 16 bit GPRs */ 73 | UD_R_AX, UD_R_CX, UD_R_DX, UD_R_BX, 74 | UD_R_SP, UD_R_BP, UD_R_SI, UD_R_DI, 75 | UD_R_R8W, UD_R_R9W, UD_R_R10W, UD_R_R11W, 76 | UD_R_R12W, UD_R_R13W, UD_R_R14W, UD_R_R15W, 77 | 78 | /* 32 bit GPRs */ 79 | UD_R_EAX, UD_R_ECX, UD_R_EDX, UD_R_EBX, 80 | UD_R_ESP, UD_R_EBP, UD_R_ESI, UD_R_EDI, 81 | UD_R_R8D, UD_R_R9D, UD_R_R10D, UD_R_R11D, 82 | UD_R_R12D, UD_R_R13D, UD_R_R14D, UD_R_R15D, 83 | 84 | /* 64 bit GPRs */ 85 | UD_R_RAX, UD_R_RCX, UD_R_RDX, UD_R_RBX, 86 | UD_R_RSP, UD_R_RBP, UD_R_RSI, UD_R_RDI, 87 | UD_R_R8, UD_R_R9, UD_R_R10, UD_R_R11, 88 | UD_R_R12, UD_R_R13, UD_R_R14, UD_R_R15, 89 | 90 | /* segment registers */ 91 | UD_R_ES, UD_R_CS, UD_R_SS, UD_R_DS, 92 | UD_R_FS, UD_R_GS, 93 | 94 | /* control registers*/ 95 | UD_R_CR0, UD_R_CR1, UD_R_CR2, UD_R_CR3, 96 | UD_R_CR4, UD_R_CR5, UD_R_CR6, UD_R_CR7, 97 | UD_R_CR8, UD_R_CR9, UD_R_CR10, UD_R_CR11, 98 | UD_R_CR12, UD_R_CR13, UD_R_CR14, UD_R_CR15, 99 | 100 | /* debug registers */ 101 | UD_R_DR0, UD_R_DR1, UD_R_DR2, UD_R_DR3, 102 | UD_R_DR4, UD_R_DR5, UD_R_DR6, UD_R_DR7, 103 | UD_R_DR8, UD_R_DR9, UD_R_DR10, UD_R_DR11, 104 | UD_R_DR12, UD_R_DR13, UD_R_DR14, UD_R_DR15, 105 | 106 | /* mmx registers */ 107 | UD_R_MM0, UD_R_MM1, UD_R_MM2, UD_R_MM3, 108 | UD_R_MM4, UD_R_MM5, UD_R_MM6, UD_R_MM7, 109 | 110 | /* x87 registers */ 111 | UD_R_ST0, UD_R_ST1, UD_R_ST2, UD_R_ST3, 112 | UD_R_ST4, UD_R_ST5, UD_R_ST6, UD_R_ST7, 113 | 114 | /* extended multimedia registers */ 115 | UD_R_XMM0, UD_R_XMM1, UD_R_XMM2, UD_R_XMM3, 116 | UD_R_XMM4, UD_R_XMM5, UD_R_XMM6, UD_R_XMM7, 117 | UD_R_XMM8, UD_R_XMM9, UD_R_XMM10, UD_R_XMM11, 118 | UD_R_XMM12, UD_R_XMM13, UD_R_XMM14, UD_R_XMM15, 119 | 120 | UD_R_RIP, 121 | 122 | /* Operand Types */ 123 | UD_OP_REG, UD_OP_MEM, UD_OP_PTR, UD_OP_IMM, 124 | UD_OP_JIMM, UD_OP_CONST 125 | }; 126 | 127 | #include "itab.h" 128 | 129 | union ud_lval { 130 | int8_t sbyte; 131 | uint8_t ubyte; 132 | int16_t sword; 133 | uint16_t uword; 134 | int32_t sdword; 135 | uint32_t udword; 136 | int64_t sqword; 137 | uint64_t uqword; 138 | struct { 139 | uint16_t seg; 140 | uint32_t off; 141 | } ptr; 142 | }; 143 | 144 | /* ----------------------------------------------------------------------------- 145 | * struct ud_operand - Disassembled instruction Operand. 146 | * ----------------------------------------------------------------------------- 147 | */ 148 | struct ud_operand { 149 | enum ud_type type; 150 | uint8_t size; 151 | enum ud_type base; 152 | enum ud_type index; 153 | uint8_t scale; 154 | uint8_t offset; 155 | union ud_lval lval; 156 | /* 157 | * internal use only 158 | */ 159 | uint64_t _legacy; /* this will be removed in 1.8 */ 160 | uint8_t _oprcode; 161 | }; 162 | 163 | /* ----------------------------------------------------------------------------- 164 | * struct ud - The udis86 object. 165 | * ----------------------------------------------------------------------------- 166 | */ 167 | struct ud 168 | { 169 | /* 170 | * input buffering 171 | */ 172 | int (*inp_hook) (struct ud*); 173 | #ifndef __UD_STANDALONE__ 174 | FILE* inp_file; 175 | #endif 176 | const uint8_t* inp_buf; 177 | size_t inp_buf_size; 178 | size_t inp_buf_index; 179 | uint8_t inp_curr; 180 | size_t inp_ctr; 181 | uint8_t inp_sess[64]; 182 | int inp_end; 183 | 184 | void (*translator)(struct ud*); 185 | uint64_t insn_offset; 186 | char insn_hexcode[64]; 187 | 188 | /* 189 | * Assembly output buffer 190 | */ 191 | char *asm_buf; 192 | size_t asm_buf_size; 193 | size_t asm_buf_fill; 194 | char asm_buf_int[128]; 195 | 196 | /* 197 | * Symbol resolver for use in the translation phase. 198 | */ 199 | const char* (*sym_resolver)(struct ud*, uint64_t addr, int64_t *offset); 200 | 201 | uint8_t dis_mode; 202 | uint64_t pc; 203 | uint8_t vendor; 204 | enum ud_mnemonic_code mnemonic; 205 | struct ud_operand operand[3]; 206 | uint8_t error; 207 | uint8_t pfx_rex; 208 | uint8_t pfx_seg; 209 | uint8_t pfx_opr; 210 | uint8_t pfx_adr; 211 | uint8_t pfx_lock; 212 | uint8_t pfx_str; 213 | uint8_t pfx_rep; 214 | uint8_t pfx_repe; 215 | uint8_t pfx_repne; 216 | uint8_t opr_mode; 217 | uint8_t adr_mode; 218 | uint8_t br_far; 219 | uint8_t br_near; 220 | uint8_t have_modrm; 221 | uint8_t modrm; 222 | uint8_t primary_opcode; 223 | void * user_opaque_data; 224 | struct ud_itab_entry * itab_entry; 225 | struct ud_lookup_table_list_entry *le; 226 | }; 227 | 228 | /* ----------------------------------------------------------------------------- 229 | * Type-definitions 230 | * ----------------------------------------------------------------------------- 231 | */ 232 | typedef enum ud_type ud_type_t; 233 | typedef enum ud_mnemonic_code ud_mnemonic_code_t; 234 | 235 | typedef struct ud ud_t; 236 | typedef struct ud_operand ud_operand_t; 237 | 238 | #define UD_SYN_INTEL ud_translate_intel 239 | #define UD_SYN_ATT ud_translate_att 240 | #define UD_EOI (-1) 241 | #define UD_INP_CACHE_SZ 32 242 | #define UD_VENDOR_AMD 0 243 | #define UD_VENDOR_INTEL 1 244 | #define UD_VENDOR_ANY 2 245 | 246 | #endif 247 | 248 | /* 249 | vim: set ts=2 sw=2 expandtab 250 | */ 251 | -------------------------------------------------------------------------------- /include/utarray.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008-2014, Troy D. Hanson http://troydhanson.github.com/uthash/ 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 12 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 13 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 14 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 15 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 16 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 17 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 18 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | */ 23 | 24 | /* a dynamic array implementation using macros 25 | */ 26 | #ifndef UTARRAY_H 27 | #define UTARRAY_H 28 | 29 | #define UTARRAY_VERSION 1.9.9 30 | 31 | #ifdef __GNUC__ 32 | #define _UNUSED_ __attribute__ ((__unused__)) 33 | #else 34 | #define _UNUSED_ 35 | #endif 36 | 37 | #include /* size_t */ 38 | #include /* memset, etc */ 39 | #include /* exit */ 40 | 41 | #define oom() exit(-1) 42 | 43 | typedef void (ctor_f)(void *dst, const void *src); 44 | typedef void (dtor_f)(void *elt); 45 | typedef void (init_f)(void *elt); 46 | typedef struct { 47 | size_t sz; 48 | init_f *init; 49 | ctor_f *copy; 50 | dtor_f *dtor; 51 | } UT_icd; 52 | 53 | typedef struct { 54 | unsigned i,n;/* i: index of next available slot, n: num slots */ 55 | UT_icd icd; /* initializer, copy and destructor functions */ 56 | char *d; /* n slots of size icd->sz*/ 57 | } UT_array; 58 | 59 | #define utarray_init(a,_icd) do { \ 60 | memset(a,0,sizeof(UT_array)); \ 61 | (a)->icd=*_icd; \ 62 | } while(0) 63 | 64 | #define utarray_done(a) do { \ 65 | if ((a)->n) { \ 66 | if ((a)->icd.dtor) { \ 67 | size_t _ut_i; \ 68 | for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \ 69 | (a)->icd.dtor(utarray_eltptr(a,_ut_i)); \ 70 | } \ 71 | } \ 72 | free((a)->d); \ 73 | } \ 74 | (a)->n=0; \ 75 | } while(0) 76 | 77 | #define utarray_new(a,_icd) do { \ 78 | a=(UT_array*)malloc(sizeof(UT_array)); \ 79 | utarray_init(a,_icd); \ 80 | } while(0) 81 | 82 | #define utarray_free(a) do { \ 83 | utarray_done(a); \ 84 | free(a); \ 85 | } while(0) 86 | 87 | #define utarray_reserve(a,by) do { \ 88 | if (((a)->i+by) > ((a)->n)) { \ 89 | while(((a)->i+by) > ((a)->n)) { (a)->n = ((a)->n ? (2*(a)->n) : 8); } \ 90 | if ( ((a)->d=(char*)realloc((a)->d, (a)->n*(a)->icd.sz)) == NULL) oom(); \ 91 | } \ 92 | } while(0) 93 | 94 | #define utarray_push_back(a,p) do { \ 95 | utarray_reserve(a,1); \ 96 | if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,(a)->i++), p); } \ 97 | else { memcpy(_utarray_eltptr(a,(a)->i++), p, (a)->icd.sz); }; \ 98 | } while(0) 99 | 100 | #define utarray_pop_back(a) do { \ 101 | if ((a)->icd.dtor) { (a)->icd.dtor( _utarray_eltptr(a,--((a)->i))); } \ 102 | else { (a)->i--; } \ 103 | } while(0) 104 | 105 | #define utarray_extend_back(a) do { \ 106 | utarray_reserve(a,1); \ 107 | if ((a)->icd.init) { (a)->icd.init(_utarray_eltptr(a,(a)->i)); } \ 108 | else { memset(_utarray_eltptr(a,(a)->i),0,(a)->icd.sz); } \ 109 | (a)->i++; \ 110 | } while(0) 111 | 112 | #define utarray_len(a) ((a)->i) 113 | 114 | #define utarray_eltptr(a,j) (((j) < (a)->i) ? _utarray_eltptr(a,j) : NULL) 115 | #define _utarray_eltptr(a,j) ((char*)((a)->d + ((a)->icd.sz*(j) ))) 116 | 117 | #define utarray_insert(a,p,j) do { \ 118 | if (j > (a)->i) utarray_resize(a,j); \ 119 | utarray_reserve(a,1); \ 120 | if ((j) < (a)->i) { \ 121 | memmove( _utarray_eltptr(a,(j)+1), _utarray_eltptr(a,j), \ 122 | ((a)->i - (j))*((a)->icd.sz)); \ 123 | } \ 124 | if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,j), p); } \ 125 | else { memcpy(_utarray_eltptr(a,j), p, (a)->icd.sz); }; \ 126 | (a)->i++; \ 127 | } while(0) 128 | 129 | #define utarray_inserta(a,w,j) do { \ 130 | if (utarray_len(w) == 0) break; \ 131 | if (j > (a)->i) utarray_resize(a,j); \ 132 | utarray_reserve(a,utarray_len(w)); \ 133 | if ((j) < (a)->i) { \ 134 | memmove(_utarray_eltptr(a,(j)+utarray_len(w)), \ 135 | _utarray_eltptr(a,j), \ 136 | ((a)->i - (j))*((a)->icd.sz)); \ 137 | } \ 138 | if ((a)->icd.copy) { \ 139 | size_t _ut_i; \ 140 | for(_ut_i=0;_ut_i<(w)->i;_ut_i++) { \ 141 | (a)->icd.copy(_utarray_eltptr(a,j+_ut_i), _utarray_eltptr(w,_ut_i)); \ 142 | } \ 143 | } else { \ 144 | memcpy(_utarray_eltptr(a,j), _utarray_eltptr(w,0), \ 145 | utarray_len(w)*((a)->icd.sz)); \ 146 | } \ 147 | (a)->i += utarray_len(w); \ 148 | } while(0) 149 | 150 | #define utarray_resize(dst,num) do { \ 151 | size_t _ut_i; \ 152 | if (dst->i > (size_t)(num)) { \ 153 | if ((dst)->icd.dtor) { \ 154 | for(_ut_i=num; _ut_i < dst->i; _ut_i++) { \ 155 | (dst)->icd.dtor(utarray_eltptr(dst,_ut_i)); \ 156 | } \ 157 | } \ 158 | } else if (dst->i < (size_t)(num)) { \ 159 | utarray_reserve(dst,num-dst->i); \ 160 | if ((dst)->icd.init) { \ 161 | for(_ut_i=dst->i; _ut_i < num; _ut_i++) { \ 162 | (dst)->icd.init(utarray_eltptr(dst,_ut_i)); \ 163 | } \ 164 | } else { \ 165 | memset(_utarray_eltptr(dst,dst->i),0,(dst)->icd.sz*(num-dst->i)); \ 166 | } \ 167 | } \ 168 | dst->i = num; \ 169 | } while(0) 170 | 171 | #define utarray_concat(dst,src) do { \ 172 | utarray_inserta((dst),(src),utarray_len(dst)); \ 173 | } while(0) 174 | 175 | #define utarray_erase(a,pos,len) do { \ 176 | if ((a)->icd.dtor) { \ 177 | size_t _ut_i; \ 178 | for(_ut_i=0; _ut_i < len; _ut_i++) { \ 179 | (a)->icd.dtor(utarray_eltptr((a),pos+_ut_i)); \ 180 | } \ 181 | } \ 182 | if ((a)->i > (pos+len)) { \ 183 | memmove( _utarray_eltptr((a),pos), _utarray_eltptr((a),pos+len), \ 184 | (((a)->i)-(pos+len))*((a)->icd.sz)); \ 185 | } \ 186 | (a)->i -= (len); \ 187 | } while(0) 188 | 189 | #define utarray_renew(a,u) do { \ 190 | if (a) utarray_clear(a); \ 191 | else utarray_new((a),(u)); \ 192 | } while(0) 193 | 194 | #define utarray_clear(a) do { \ 195 | if ((a)->i > 0) { \ 196 | if ((a)->icd.dtor) { \ 197 | size_t _ut_i; \ 198 | for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \ 199 | (a)->icd.dtor(utarray_eltptr(a,_ut_i)); \ 200 | } \ 201 | } \ 202 | (a)->i = 0; \ 203 | } \ 204 | } while(0) 205 | 206 | #define utarray_sort(a,cmp) do { \ 207 | qsort((a)->d, (a)->i, (a)->icd.sz, cmp); \ 208 | } while(0) 209 | 210 | #define utarray_find(a,v,cmp) bsearch((v),(a)->d,(a)->i,(a)->icd.sz,cmp) 211 | 212 | #define utarray_front(a) (((a)->i) ? (_utarray_eltptr(a,0)) : NULL) 213 | #define utarray_next(a,e) (((e)==NULL) ? utarray_front(a) : ((((a)->i) > (utarray_eltidx(a,e)+1)) ? _utarray_eltptr(a,utarray_eltidx(a,e)+1) : NULL)) 214 | #define utarray_prev(a,e) (((e)==NULL) ? utarray_back(a) : ((utarray_eltidx(a,e) > 0) ? _utarray_eltptr(a,utarray_eltidx(a,e)-1) : NULL)) 215 | #define utarray_back(a) (((a)->i) ? (_utarray_eltptr(a,(a)->i-1)) : NULL) 216 | #define utarray_eltidx(a,e) (((char*)(e) >= (char*)((a)->d)) ? (((char*)(e) - (char*)((a)->d))/(size_t)(a)->icd.sz) : -1) 217 | 218 | /* last we pre-define a few icd for common utarrays of ints and strings */ 219 | static void utarray_str_cpy(void *dst, const void *src) { 220 | char **_src = (char**)src, **_dst = (char**)dst; 221 | *_dst = (*_src == NULL) ? NULL : strdup(*_src); 222 | } 223 | static void utarray_str_dtor(void *elt) { 224 | char **eltc = (char**)elt; 225 | if (*eltc) free(*eltc); 226 | } 227 | static const UT_icd ut_str_icd _UNUSED_ = {sizeof(char*),NULL,utarray_str_cpy,utarray_str_dtor}; 228 | static const UT_icd ut_int_icd _UNUSED_ = {sizeof(int),NULL,NULL,NULL}; 229 | static const UT_icd ut_ptr_icd _UNUSED_ = {sizeof(void*),NULL,NULL,NULL}; 230 | 231 | 232 | #endif /* UTARRAY_H */ 233 | -------------------------------------------------------------------------------- /libudis86/itab.h: -------------------------------------------------------------------------------- 1 | #ifndef UD_ITAB_H 2 | #define UD_ITAB_H 3 | 4 | /* itab.h -- generated by udis86:scripts/ud_itab.py, do no edit */ 5 | 6 | /* ud_table_type -- lookup table types (see decode.c) */ 7 | enum ud_table_type { 8 | UD_TAB__OPC_TABLE, 9 | UD_TAB__OPC_X87, 10 | UD_TAB__OPC_MOD, 11 | UD_TAB__OPC_VEX_M, 12 | UD_TAB__OPC_VEX_P, 13 | UD_TAB__OPC_RM, 14 | UD_TAB__OPC_VENDOR, 15 | UD_TAB__OPC_OSIZE, 16 | UD_TAB__OPC_MODE, 17 | UD_TAB__OPC_3DNOW, 18 | UD_TAB__OPC_REG, 19 | UD_TAB__OPC_ASIZE, 20 | UD_TAB__OPC_SSE 21 | }; 22 | 23 | /* ud_mnemonic -- mnemonic constants */ 24 | enum ud_mnemonic_code { 25 | UD_Iinvalid, 26 | UD_I3dnow, 27 | UD_Inone, 28 | UD_Idb, 29 | UD_Ipause, 30 | UD_Iaaa, 31 | UD_Iaad, 32 | UD_Iaam, 33 | UD_Iaas, 34 | UD_Iadc, 35 | UD_Iadd, 36 | UD_Iaddpd, 37 | UD_Iaddps, 38 | UD_Iaddsd, 39 | UD_Iaddss, 40 | UD_Iand, 41 | UD_Iandpd, 42 | UD_Iandps, 43 | UD_Iandnpd, 44 | UD_Iandnps, 45 | UD_Iarpl, 46 | UD_Imovsxd, 47 | UD_Ibound, 48 | UD_Ibsf, 49 | UD_Ibsr, 50 | UD_Ibswap, 51 | UD_Ibt, 52 | UD_Ibtc, 53 | UD_Ibtr, 54 | UD_Ibts, 55 | UD_Icall, 56 | UD_Icbw, 57 | UD_Icwde, 58 | UD_Icdqe, 59 | UD_Iclc, 60 | UD_Icld, 61 | UD_Iclflush, 62 | UD_Iclgi, 63 | UD_Icli, 64 | UD_Iclts, 65 | UD_Icmc, 66 | UD_Icmovo, 67 | UD_Icmovno, 68 | UD_Icmovb, 69 | UD_Icmovae, 70 | UD_Icmovz, 71 | UD_Icmovnz, 72 | UD_Icmovbe, 73 | UD_Icmova, 74 | UD_Icmovs, 75 | UD_Icmovns, 76 | UD_Icmovp, 77 | UD_Icmovnp, 78 | UD_Icmovl, 79 | UD_Icmovge, 80 | UD_Icmovle, 81 | UD_Icmovg, 82 | UD_Icmp, 83 | UD_Icmppd, 84 | UD_Icmpps, 85 | UD_Icmpsb, 86 | UD_Icmpsw, 87 | UD_Icmpsd, 88 | UD_Icmpsq, 89 | UD_Icmpss, 90 | UD_Icmpxchg, 91 | UD_Icmpxchg8b, 92 | UD_Icmpxchg16b, 93 | UD_Icomisd, 94 | UD_Icomiss, 95 | UD_Icpuid, 96 | UD_Icvtdq2pd, 97 | UD_Icvtdq2ps, 98 | UD_Icvtpd2dq, 99 | UD_Icvtpd2pi, 100 | UD_Icvtpd2ps, 101 | UD_Icvtpi2ps, 102 | UD_Icvtpi2pd, 103 | UD_Icvtps2dq, 104 | UD_Icvtps2pi, 105 | UD_Icvtps2pd, 106 | UD_Icvtsd2si, 107 | UD_Icvtsd2ss, 108 | UD_Icvtsi2ss, 109 | UD_Icvtss2si, 110 | UD_Icvtss2sd, 111 | UD_Icvttpd2pi, 112 | UD_Icvttpd2dq, 113 | UD_Icvttps2dq, 114 | UD_Icvttps2pi, 115 | UD_Icvttsd2si, 116 | UD_Icvtsi2sd, 117 | UD_Icvttss2si, 118 | UD_Icwd, 119 | UD_Icdq, 120 | UD_Icqo, 121 | UD_Idaa, 122 | UD_Idas, 123 | UD_Idec, 124 | UD_Idiv, 125 | UD_Idivpd, 126 | UD_Idivps, 127 | UD_Idivsd, 128 | UD_Idivss, 129 | UD_Iemms, 130 | UD_Ienter, 131 | UD_If2xm1, 132 | UD_Ifabs, 133 | UD_Ifadd, 134 | UD_Ifaddp, 135 | UD_Ifbld, 136 | UD_Ifbstp, 137 | UD_Ifchs, 138 | UD_Ifclex, 139 | UD_Ifcmovb, 140 | UD_Ifcmove, 141 | UD_Ifcmovbe, 142 | UD_Ifcmovu, 143 | UD_Ifcmovnb, 144 | UD_Ifcmovne, 145 | UD_Ifcmovnbe, 146 | UD_Ifcmovnu, 147 | UD_Ifucomi, 148 | UD_Ifcom, 149 | UD_Ifcom2, 150 | UD_Ifcomp3, 151 | UD_Ifcomi, 152 | UD_Ifucomip, 153 | UD_Ifcomip, 154 | UD_Ifcomp, 155 | UD_Ifcomp5, 156 | UD_Ifcompp, 157 | UD_Ifcos, 158 | UD_Ifdecstp, 159 | UD_Ifdiv, 160 | UD_Ifdivp, 161 | UD_Ifdivr, 162 | UD_Ifdivrp, 163 | UD_Ifemms, 164 | UD_Iffree, 165 | UD_Iffreep, 166 | UD_Ificom, 167 | UD_Ificomp, 168 | UD_Ifild, 169 | UD_Ifincstp, 170 | UD_Ifninit, 171 | UD_Ifiadd, 172 | UD_Ifidivr, 173 | UD_Ifidiv, 174 | UD_Ifisub, 175 | UD_Ifisubr, 176 | UD_Ifist, 177 | UD_Ifistp, 178 | UD_Ifisttp, 179 | UD_Ifld, 180 | UD_Ifld1, 181 | UD_Ifldl2t, 182 | UD_Ifldl2e, 183 | UD_Ifldpi, 184 | UD_Ifldlg2, 185 | UD_Ifldln2, 186 | UD_Ifldz, 187 | UD_Ifldcw, 188 | UD_Ifldenv, 189 | UD_Ifmul, 190 | UD_Ifmulp, 191 | UD_Ifimul, 192 | UD_Ifnop, 193 | UD_Ifpatan, 194 | UD_Ifprem, 195 | UD_Ifprem1, 196 | UD_Ifptan, 197 | UD_Ifrndint, 198 | UD_Ifrstor, 199 | UD_Ifnsave, 200 | UD_Ifscale, 201 | UD_Ifsin, 202 | UD_Ifsincos, 203 | UD_Ifsqrt, 204 | UD_Ifstp, 205 | UD_Ifstp1, 206 | UD_Ifstp8, 207 | UD_Ifstp9, 208 | UD_Ifst, 209 | UD_Ifnstcw, 210 | UD_Ifnstenv, 211 | UD_Ifnstsw, 212 | UD_Ifsub, 213 | UD_Ifsubp, 214 | UD_Ifsubr, 215 | UD_Ifsubrp, 216 | UD_Iftst, 217 | UD_Ifucom, 218 | UD_Ifucomp, 219 | UD_Ifucompp, 220 | UD_Ifxam, 221 | UD_Ifxch, 222 | UD_Ifxch4, 223 | UD_Ifxch7, 224 | UD_Ifxrstor, 225 | UD_Ifxsave, 226 | UD_Ifxtract, 227 | UD_Ifyl2x, 228 | UD_Ifyl2xp1, 229 | UD_Ihlt, 230 | UD_Iidiv, 231 | UD_Iin, 232 | UD_Iimul, 233 | UD_Iinc, 234 | UD_Iinsb, 235 | UD_Iinsw, 236 | UD_Iinsd, 237 | UD_Iint1, 238 | UD_Iint3, 239 | UD_Iint, 240 | UD_Iinto, 241 | UD_Iinvd, 242 | UD_Iinvept, 243 | UD_Iinvlpg, 244 | UD_Iinvlpga, 245 | UD_Iinvvpid, 246 | UD_Iiretw, 247 | UD_Iiretd, 248 | UD_Iiretq, 249 | UD_Ijo, 250 | UD_Ijno, 251 | UD_Ijb, 252 | UD_Ijae, 253 | UD_Ijz, 254 | UD_Ijnz, 255 | UD_Ijbe, 256 | UD_Ija, 257 | UD_Ijs, 258 | UD_Ijns, 259 | UD_Ijp, 260 | UD_Ijnp, 261 | UD_Ijl, 262 | UD_Ijge, 263 | UD_Ijle, 264 | UD_Ijg, 265 | UD_Ijcxz, 266 | UD_Ijecxz, 267 | UD_Ijrcxz, 268 | UD_Ijmp, 269 | UD_Ilahf, 270 | UD_Ilar, 271 | UD_Ilddqu, 272 | UD_Ildmxcsr, 273 | UD_Ilds, 274 | UD_Ilea, 275 | UD_Iles, 276 | UD_Ilfs, 277 | UD_Ilgs, 278 | UD_Ilidt, 279 | UD_Ilss, 280 | UD_Ileave, 281 | UD_Ilfence, 282 | UD_Ilgdt, 283 | UD_Illdt, 284 | UD_Ilmsw, 285 | UD_Ilock, 286 | UD_Ilodsb, 287 | UD_Ilodsw, 288 | UD_Ilodsd, 289 | UD_Ilodsq, 290 | UD_Iloopne, 291 | UD_Iloope, 292 | UD_Iloop, 293 | UD_Ilsl, 294 | UD_Iltr, 295 | UD_Imaskmovq, 296 | UD_Imaxpd, 297 | UD_Imaxps, 298 | UD_Imaxsd, 299 | UD_Imaxss, 300 | UD_Imfence, 301 | UD_Iminpd, 302 | UD_Iminps, 303 | UD_Iminsd, 304 | UD_Iminss, 305 | UD_Imonitor, 306 | UD_Imontmul, 307 | UD_Imov, 308 | UD_Imovapd, 309 | UD_Imovaps, 310 | UD_Imovd, 311 | UD_Imovhpd, 312 | UD_Imovhps, 313 | UD_Imovlhps, 314 | UD_Imovlpd, 315 | UD_Imovlps, 316 | UD_Imovhlps, 317 | UD_Imovmskpd, 318 | UD_Imovmskps, 319 | UD_Imovntdq, 320 | UD_Imovnti, 321 | UD_Imovntpd, 322 | UD_Imovntps, 323 | UD_Imovntq, 324 | UD_Imovq, 325 | UD_Imovsb, 326 | UD_Imovsw, 327 | UD_Imovsd, 328 | UD_Imovsq, 329 | UD_Imovss, 330 | UD_Imovsx, 331 | UD_Imovupd, 332 | UD_Imovups, 333 | UD_Imovzx, 334 | UD_Imul, 335 | UD_Imulpd, 336 | UD_Imulps, 337 | UD_Imulsd, 338 | UD_Imulss, 339 | UD_Imwait, 340 | UD_Ineg, 341 | UD_Inop, 342 | UD_Inot, 343 | UD_Ior, 344 | UD_Iorpd, 345 | UD_Iorps, 346 | UD_Iout, 347 | UD_Ioutsb, 348 | UD_Ioutsw, 349 | UD_Ioutsd, 350 | UD_Ipacksswb, 351 | UD_Ipackssdw, 352 | UD_Ipackuswb, 353 | UD_Ipaddb, 354 | UD_Ipaddw, 355 | UD_Ipaddd, 356 | UD_Ipaddsb, 357 | UD_Ipaddsw, 358 | UD_Ipaddusb, 359 | UD_Ipaddusw, 360 | UD_Ipand, 361 | UD_Ipandn, 362 | UD_Ipavgb, 363 | UD_Ipavgw, 364 | UD_Ipcmpeqb, 365 | UD_Ipcmpeqw, 366 | UD_Ipcmpeqd, 367 | UD_Ipcmpgtb, 368 | UD_Ipcmpgtw, 369 | UD_Ipcmpgtd, 370 | UD_Ipextrb, 371 | UD_Ipextrd, 372 | UD_Ipextrq, 373 | UD_Ipextrw, 374 | UD_Ipinsrb, 375 | UD_Ipinsrw, 376 | UD_Ipinsrd, 377 | UD_Ipinsrq, 378 | UD_Ipmaddwd, 379 | UD_Ipmaxsw, 380 | UD_Ipmaxub, 381 | UD_Ipminsw, 382 | UD_Ipminub, 383 | UD_Ipmovmskb, 384 | UD_Ipmulhuw, 385 | UD_Ipmulhw, 386 | UD_Ipmullw, 387 | UD_Ipop, 388 | UD_Ipopa, 389 | UD_Ipopad, 390 | UD_Ipopfw, 391 | UD_Ipopfd, 392 | UD_Ipopfq, 393 | UD_Ipor, 394 | UD_Iprefetch, 395 | UD_Iprefetchnta, 396 | UD_Iprefetcht0, 397 | UD_Iprefetcht1, 398 | UD_Iprefetcht2, 399 | UD_Ipsadbw, 400 | UD_Ipshufw, 401 | UD_Ipsllw, 402 | UD_Ipslld, 403 | UD_Ipsllq, 404 | UD_Ipsraw, 405 | UD_Ipsrad, 406 | UD_Ipsrlw, 407 | UD_Ipsrld, 408 | UD_Ipsrlq, 409 | UD_Ipsubb, 410 | UD_Ipsubw, 411 | UD_Ipsubd, 412 | UD_Ipsubsb, 413 | UD_Ipsubsw, 414 | UD_Ipsubusb, 415 | UD_Ipsubusw, 416 | UD_Ipunpckhbw, 417 | UD_Ipunpckhwd, 418 | UD_Ipunpckhdq, 419 | UD_Ipunpcklbw, 420 | UD_Ipunpcklwd, 421 | UD_Ipunpckldq, 422 | UD_Ipi2fw, 423 | UD_Ipi2fd, 424 | UD_Ipf2iw, 425 | UD_Ipf2id, 426 | UD_Ipfnacc, 427 | UD_Ipfpnacc, 428 | UD_Ipfcmpge, 429 | UD_Ipfmin, 430 | UD_Ipfrcp, 431 | UD_Ipfrsqrt, 432 | UD_Ipfsub, 433 | UD_Ipfadd, 434 | UD_Ipfcmpgt, 435 | UD_Ipfmax, 436 | UD_Ipfrcpit1, 437 | UD_Ipfrsqit1, 438 | UD_Ipfsubr, 439 | UD_Ipfacc, 440 | UD_Ipfcmpeq, 441 | UD_Ipfmul, 442 | UD_Ipfrcpit2, 443 | UD_Ipmulhrw, 444 | UD_Ipswapd, 445 | UD_Ipavgusb, 446 | UD_Ipush, 447 | UD_Ipusha, 448 | UD_Ipushad, 449 | UD_Ipushfw, 450 | UD_Ipushfd, 451 | UD_Ipushfq, 452 | UD_Ipxor, 453 | UD_Ircl, 454 | UD_Ircr, 455 | UD_Irol, 456 | UD_Iror, 457 | UD_Ircpps, 458 | UD_Ircpss, 459 | UD_Irdmsr, 460 | UD_Irdpmc, 461 | UD_Irdtsc, 462 | UD_Irdtscp, 463 | UD_Irepne, 464 | UD_Irep, 465 | UD_Iret, 466 | UD_Iretf, 467 | UD_Irsm, 468 | UD_Irsqrtps, 469 | UD_Irsqrtss, 470 | UD_Isahf, 471 | UD_Isalc, 472 | UD_Isar, 473 | UD_Ishl, 474 | UD_Ishr, 475 | UD_Isbb, 476 | UD_Iscasb, 477 | UD_Iscasw, 478 | UD_Iscasd, 479 | UD_Iscasq, 480 | UD_Iseto, 481 | UD_Isetno, 482 | UD_Isetb, 483 | UD_Isetae, 484 | UD_Isetz, 485 | UD_Isetnz, 486 | UD_Isetbe, 487 | UD_Iseta, 488 | UD_Isets, 489 | UD_Isetns, 490 | UD_Isetp, 491 | UD_Isetnp, 492 | UD_Isetl, 493 | UD_Isetge, 494 | UD_Isetle, 495 | UD_Isetg, 496 | UD_Isfence, 497 | UD_Isgdt, 498 | UD_Ishld, 499 | UD_Ishrd, 500 | UD_Ishufpd, 501 | UD_Ishufps, 502 | UD_Isidt, 503 | UD_Isldt, 504 | UD_Ismsw, 505 | UD_Isqrtps, 506 | UD_Isqrtpd, 507 | UD_Isqrtsd, 508 | UD_Isqrtss, 509 | UD_Istc, 510 | UD_Istd, 511 | UD_Istgi, 512 | UD_Isti, 513 | UD_Iskinit, 514 | UD_Istmxcsr, 515 | UD_Istosb, 516 | UD_Istosw, 517 | UD_Istosd, 518 | UD_Istosq, 519 | UD_Istr, 520 | UD_Isub, 521 | UD_Isubpd, 522 | UD_Isubps, 523 | UD_Isubsd, 524 | UD_Isubss, 525 | UD_Iswapgs, 526 | UD_Isyscall, 527 | UD_Isysenter, 528 | UD_Isysexit, 529 | UD_Isysret, 530 | UD_Itest, 531 | UD_Iucomisd, 532 | UD_Iucomiss, 533 | UD_Iud2, 534 | UD_Iunpckhpd, 535 | UD_Iunpckhps, 536 | UD_Iunpcklps, 537 | UD_Iunpcklpd, 538 | UD_Iverr, 539 | UD_Iverw, 540 | UD_Ivmcall, 541 | UD_Ivmclear, 542 | UD_Ivmxon, 543 | UD_Ivmptrld, 544 | UD_Ivmptrst, 545 | UD_Ivmlaunch, 546 | UD_Ivmresume, 547 | UD_Ivmxoff, 548 | UD_Ivmread, 549 | UD_Ivmwrite, 550 | UD_Ivmrun, 551 | UD_Ivmmcall, 552 | UD_Ivmload, 553 | UD_Ivmsave, 554 | UD_Iwait, 555 | UD_Iwbinvd, 556 | UD_Iwrmsr, 557 | UD_Ixadd, 558 | UD_Ixchg, 559 | UD_Ixgetbv, 560 | UD_Ixlatb, 561 | UD_Ixor, 562 | UD_Ixorpd, 563 | UD_Ixorps, 564 | UD_Ixcryptecb, 565 | UD_Ixcryptcbc, 566 | UD_Ixcryptctr, 567 | UD_Ixcryptcfb, 568 | UD_Ixcryptofb, 569 | UD_Ixrstor, 570 | UD_Ixsave, 571 | UD_Ixsetbv, 572 | UD_Ixsha1, 573 | UD_Ixsha256, 574 | UD_Ixstore, 575 | UD_Iaesdec, 576 | UD_Iaesdeclast, 577 | UD_Iaesenc, 578 | UD_Iaesenclast, 579 | UD_Iaesimc, 580 | UD_Iaeskeygenassist, 581 | UD_Ipclmulqdq, 582 | UD_Igetsec, 583 | UD_Imovdqa, 584 | UD_Imaskmovdqu, 585 | UD_Imovdq2q, 586 | UD_Imovdqu, 587 | UD_Imovq2dq, 588 | UD_Ipaddq, 589 | UD_Ipsubq, 590 | UD_Ipmuludq, 591 | UD_Ipshufhw, 592 | UD_Ipshuflw, 593 | UD_Ipshufd, 594 | UD_Ipslldq, 595 | UD_Ipsrldq, 596 | UD_Ipunpckhqdq, 597 | UD_Ipunpcklqdq, 598 | UD_Iaddsubpd, 599 | UD_Iaddsubps, 600 | UD_Ihaddpd, 601 | UD_Ihaddps, 602 | UD_Ihsubpd, 603 | UD_Ihsubps, 604 | UD_Imovddup, 605 | UD_Imovshdup, 606 | UD_Imovsldup, 607 | UD_Ipabsb, 608 | UD_Ipabsw, 609 | UD_Ipabsd, 610 | UD_Ipshufb, 611 | UD_Iphaddw, 612 | UD_Iphaddd, 613 | UD_Iphaddsw, 614 | UD_Ipmaddubsw, 615 | UD_Iphsubw, 616 | UD_Iphsubd, 617 | UD_Iphsubsw, 618 | UD_Ipsignb, 619 | UD_Ipsignd, 620 | UD_Ipsignw, 621 | UD_Ipmulhrsw, 622 | UD_Ipalignr, 623 | UD_Ipblendvb, 624 | UD_Ipmuldq, 625 | UD_Ipminsb, 626 | UD_Ipminsd, 627 | UD_Ipminuw, 628 | UD_Ipminud, 629 | UD_Ipmaxsb, 630 | UD_Ipmaxsd, 631 | UD_Ipmaxud, 632 | UD_Ipmaxuw, 633 | UD_Ipmulld, 634 | UD_Iphminposuw, 635 | UD_Iroundps, 636 | UD_Iroundpd, 637 | UD_Iroundss, 638 | UD_Iroundsd, 639 | UD_Iblendpd, 640 | UD_Ipblendw, 641 | UD_Iblendps, 642 | UD_Iblendvpd, 643 | UD_Iblendvps, 644 | UD_Idpps, 645 | UD_Idppd, 646 | UD_Impsadbw, 647 | UD_Iextractps, 648 | UD_Iinsertps, 649 | UD_Imovntdqa, 650 | UD_Ipackusdw, 651 | UD_Ipmovsxbw, 652 | UD_Ipmovsxbd, 653 | UD_Ipmovsxbq, 654 | UD_Ipmovsxwd, 655 | UD_Ipmovsxwq, 656 | UD_Ipmovsxdq, 657 | UD_Ipmovzxbw, 658 | UD_Ipmovzxbd, 659 | UD_Ipmovzxbq, 660 | UD_Ipmovzxwd, 661 | UD_Ipmovzxwq, 662 | UD_Ipmovzxdq, 663 | UD_Ipcmpeqq, 664 | UD_Ipopcnt, 665 | UD_Iptest, 666 | UD_Ipcmpestri, 667 | UD_Ipcmpestrm, 668 | UD_Ipcmpgtq, 669 | UD_Ipcmpistri, 670 | UD_Ipcmpistrm, 671 | UD_Imovbe, 672 | UD_Icrc32, 673 | UD_MAX_MNEMONIC_CODE 674 | } UD_ATTR_PACKED; 675 | 676 | extern const char * ud_mnemonics_str[]; 677 | 678 | #endif /* UD_ITAB_H */ 679 | -------------------------------------------------------------------------------- /src/set_io_param.c: -------------------------------------------------------------------------------- 1 | // gcc -O1 -o set_io_param set_io_param.c -lrt 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #define MAX_FS_SERVER (8) 23 | #define MAX_LEN_FS_NAME (16) 24 | 25 | uint64_t t_Updated_Param=0; 26 | int UpdateFlag[MAX_FS_SERVER]; 27 | float Max_open_Freq[MAX_FS_SERVER]; 28 | float Max_lxstat_Freq[MAX_FS_SERVER]; 29 | float t_threshold_open[MAX_FS_SERVER]; 30 | float t_threshold_lxstat[MAX_FS_SERVER]; 31 | uint64_t t_threshold_open_int64[MAX_FS_SERVER]; 32 | uint64_t t_threshold_lxstat_int64[MAX_FS_SERVER]; 33 | 34 | float Max_open_Freq_Default[MAX_FS_SERVER]; 35 | float Max_lxstat_Freq_Default[MAX_FS_SERVER]; 36 | float t_threshold_open_Default[MAX_FS_SERVER]; 37 | float t_threshold_lxstat_Default[MAX_FS_SERVER]; 38 | 39 | float scale=1.0; 40 | int n_fs_server=0; 41 | 42 | uint64_t *p_t_Updated_Param=NULL; 43 | uint64_t *p_t_threshold_open_int64=NULL; 44 | uint64_t *p_t_threshold_lxstat_int64=NULL; 45 | float *p_Max_open_Freq_Share=NULL; 46 | float *p_Max_lxstat_Freq_Share=NULL; 47 | uint64_t *p_Disabled=NULL; 48 | uint64_t *p_Param_Mem_Ready=NULL; 49 | char *p_FS_Tag_List[MAX_FS_SERVER]; // 16 bytes per record 50 | int *p_FS_Tag_Len; 51 | 52 | char *szConfigName=NULL; 53 | 54 | 55 | int shm_param_fd; // fd for mutex 56 | void *p_param_shm=NULL; // ptr to shared memory 57 | int nSize_Shared_Param_Data=0;// the number of bytes of shared data 58 | 59 | float freq; 60 | 61 | /*__attribute__((naked)) unsigned long int rdtscp(void) 62 | { 63 | __asm { 64 | rdtscp 65 | shl rdx,0x20 66 | add rax,rdx 67 | ret 68 | } 69 | } 70 | */ 71 | 72 | unsigned long int rdtscp(void) 73 | { 74 | unsigned long int rax, rdx; 75 | asm volatile ( "rdtscp\n" : "=a" (rax), "=d" (rdx) : : ); 76 | return (rdx << 32) + rax; 77 | } 78 | 79 | void Publish_Parameters(void); 80 | void Report_Parameters(void); 81 | float Get_Freq(void); 82 | void Read_Default_Param(void); 83 | void Print_Default_Param(void); 84 | void Print_Usage_Info(void); 85 | 86 | void Print_Usage_Info(void) 87 | { 88 | printf("Usage:\n"); 89 | printf("1. set_io_param # Show the status and parameters.\n"); 90 | printf("2. set_io_param 0 # Disable OOOPS\n"); 91 | printf("3. set_io_param 1 # Enable OOOPS.\n"); 92 | printf("4. set_io_param [ server_idx t_open max_open_freq t_stat max_stat_freq ]\n"); 93 | printf("5. set_io_param server_idx [ low / medium / high / unlimit ]\n"); 94 | exit(1); 95 | } 96 | 97 | int main(int argc, char *argv[]) 98 | { 99 | int nset, i, j, fs_idx, uid, bEnabled; 100 | char mutex_name[64]; 101 | 102 | memset(UpdateFlag, 0, sizeof(int)*MAX_FS_SERVER); 103 | 104 | freq = Get_Freq(); 105 | Read_Default_Param(); 106 | 107 | 108 | if( ( (argc-1) % 5) == 0 ) { // [ server_idx, t_open, max_open_freq, t_lxstat, max_stat_freq ] 109 | nset = (argc-1) / 5; 110 | 111 | for(i=0; i>1] = f; 356 | df = (f > f_Sys) ? (f - f_Sys) : (f_Sys - f); 357 | if( df < df_Min) { 358 | df_Min = df; 359 | f_Use = f; 360 | Config_Use = i; 361 | } 362 | } 363 | } 364 | 365 | p_Use = szBuff + PosList[Config_Use] + 6; 366 | while(1) { 367 | if(*p_Use == 0xA) { // new line. Find the beginning of real parameter region 368 | p_Use = p_Use + 1; 369 | break; 370 | } 371 | p_Use = p_Use + 1; 372 | } 373 | szBuff[PosList[Config_Use + 1] - 1] = 0; // Find the end of parameter region 374 | 375 | nParam = sscanf(p_Use, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", 376 | szItems[0], szItems[1], szItems[2], szItems[3], szItems[4], szItems[5], szItems[6], szItems[7], szItems[8], szItems[9], 377 | szItems[10], szItems[11], szItems[12], szItems[13], szItems[14], szItems[15], szItems[16], szItems[17], szItems[18], szItems[19], 378 | szItems[20], szItems[21], szItems[22], szItems[23], szItems[24], szItems[25], szItems[26], szItems[27], szItems[28], szItems[29], 379 | szItems[30], szItems[31], szItems[32], szItems[33], szItems[34], szItems[35], szItems[36], szItems[37], szItems[38], szItems[39], 380 | szItems[40], szItems[41], szItems[42], szItems[43], szItems[44], szItems[45], szItems[46], szItems[47], szItems[48], szItems[49], 381 | szItems[50], szItems[51], szItems[52], szItems[53], szItems[54], szItems[55], szItems[56], szItems[57], szItems[58], szItems[59], 382 | szItems[60], szItems[61], szItems[62], szItems[63], szItems[64], szItems[65], szItems[66], szItems[67], szItems[68], szItems[69], 383 | szItems[70], szItems[71], szItems[72], szItems[73], szItems[74], szItems[75], szItems[76], szItems[77], szItems[78], szItems[79] 384 | ); 385 | 386 | n_fs_server = nParam / N_ITEM_PER_REC; 387 | 388 | 389 | for(i=0; i /* size_t */ 79 | typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode; 80 | 81 | 82 | /* **************************** 83 | * API modifier 84 | ******************************/ 85 | /** XXH_INLINE_ALL (and XXH_PRIVATE_API) 86 | * This is useful to include xxhash functions in `static` mode 87 | * in order to inline them, and remove their symbol from the public list. 88 | * Inlining can offer dramatic performance improvement on small keys. 89 | * Methodology : 90 | * #define XXH_INLINE_ALL 91 | * #include "xxhash.h" 92 | * `xxhash.c` is automatically included. 93 | * It's not useful to compile and link it as a separate module. 94 | */ 95 | #if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) 96 | # ifndef XXH_STATIC_LINKING_ONLY 97 | # define XXH_STATIC_LINKING_ONLY 98 | # endif 99 | # if defined(__GNUC__) 100 | # define XXH_PUBLIC_API static __inline __attribute__((unused)) 101 | # elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) 102 | # define XXH_PUBLIC_API static inline 103 | # elif defined(_MSC_VER) 104 | # define XXH_PUBLIC_API static __inline 105 | # else 106 | /* this version may generate warnings for unused static functions */ 107 | # define XXH_PUBLIC_API static 108 | # endif 109 | #else 110 | # define XXH_PUBLIC_API /* do nothing */ 111 | #endif /* XXH_INLINE_ALL || XXH_PRIVATE_API */ 112 | 113 | /*! XXH_NAMESPACE, aka Namespace Emulation : 114 | * 115 | * If you want to include _and expose_ xxHash functions from within your own library, 116 | * but also want to avoid symbol collisions with other libraries which may also include xxHash, 117 | * 118 | * you can use XXH_NAMESPACE, to automatically prefix any public symbol from xxhash library 119 | * with the value of XXH_NAMESPACE (therefore, avoid NULL and numeric values). 120 | * 121 | * Note that no change is required within the calling program as long as it includes `xxhash.h` : 122 | * regular symbol name will be automatically translated by this header. 123 | */ 124 | #ifdef XXH_NAMESPACE 125 | # define XXH_CAT(A,B) A##B 126 | # define XXH_NAME2(A,B) XXH_CAT(A,B) 127 | # define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber) 128 | # define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32) 129 | # define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState) 130 | # define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState) 131 | # define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset) 132 | # define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update) 133 | # define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest) 134 | # define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState) 135 | # define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash) 136 | # define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical) 137 | # define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64) 138 | # define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState) 139 | # define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState) 140 | # define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset) 141 | # define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update) 142 | # define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest) 143 | # define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState) 144 | # define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash) 145 | # define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical) 146 | #endif 147 | 148 | 149 | /* ************************************* 150 | * Version 151 | ***************************************/ 152 | #define XXH_VERSION_MAJOR 0 153 | #define XXH_VERSION_MINOR 6 154 | #define XXH_VERSION_RELEASE 5 155 | #define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE) 156 | XXH_PUBLIC_API unsigned XXH_versionNumber (void); 157 | 158 | 159 | /*-********************************************************************** 160 | * 32-bit hash 161 | ************************************************************************/ 162 | typedef unsigned int XXH32_hash_t; 163 | 164 | /*! XXH32() : 165 | Calculate the 32-bit hash of sequence "length" bytes stored at memory address "input". 166 | The memory between input & input+length must be valid (allocated and read-accessible). 167 | "seed" can be used to alter the result predictably. 168 | Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s */ 169 | XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t length, unsigned int seed); 170 | 171 | /*====== Streaming ======*/ 172 | typedef struct XXH32_state_s XXH32_state_t; /* incomplete type */ 173 | XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void); 174 | XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr); 175 | XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dst_state, const XXH32_state_t* src_state); 176 | 177 | XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned int seed); 178 | XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length); 179 | XXH_PUBLIC_API XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr); 180 | 181 | /* 182 | * Streaming functions generate the xxHash of an input provided in multiple segments. 183 | * Note that, for small input, they are slower than single-call functions, due to state management. 184 | * For small inputs, prefer `XXH32()` and `XXH64()`, which are better optimized. 185 | * 186 | * XXH state must first be allocated, using XXH*_createState() . 187 | * 188 | * Start a new hash by initializing state with a seed, using XXH*_reset(). 189 | * 190 | * Then, feed the hash state by calling XXH*_update() as many times as necessary. 191 | * The function returns an error code, with 0 meaning OK, and any other value meaning there is an error. 192 | * 193 | * Finally, a hash value can be produced anytime, by using XXH*_digest(). 194 | * This function returns the nn-bits hash as an int or long long. 195 | * 196 | * It's still possible to continue inserting input into the hash state after a digest, 197 | * and generate some new hashes later on, by calling again XXH*_digest(). 198 | * 199 | * When done, free XXH state space if it was allocated dynamically. 200 | */ 201 | 202 | /*====== Canonical representation ======*/ 203 | 204 | typedef struct { unsigned char digest[4]; } XXH32_canonical_t; 205 | XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash); 206 | XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src); 207 | 208 | /* Default result type for XXH functions are primitive unsigned 32 and 64 bits. 209 | * The canonical representation uses human-readable write convention, aka big-endian (large digits first). 210 | * These functions allow transformation of hash result into and from its canonical format. 211 | * This way, hash values can be written into a file / memory, and remain comparable on different systems and programs. 212 | */ 213 | 214 | 215 | #ifndef XXH_NO_LONG_LONG 216 | /*-********************************************************************** 217 | * 64-bit hash 218 | ************************************************************************/ 219 | typedef unsigned long long XXH64_hash_t; 220 | 221 | /*! XXH64() : 222 | Calculate the 64-bit hash of sequence of length "len" stored at memory address "input". 223 | "seed" can be used to alter the result predictably. 224 | This function runs faster on 64-bit systems, but slower on 32-bit systems (see benchmark). 225 | */ 226 | XXH_PUBLIC_API XXH64_hash_t XXH64 (const void* input, size_t length, unsigned long long seed); 227 | 228 | /*====== Streaming ======*/ 229 | typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */ 230 | XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void); 231 | XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr); 232 | XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dst_state, const XXH64_state_t* src_state); 233 | 234 | XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed); 235 | XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length); 236 | XXH_PUBLIC_API XXH64_hash_t XXH64_digest (const XXH64_state_t* statePtr); 237 | 238 | /*====== Canonical representation ======*/ 239 | typedef struct { unsigned char digest[8]; } XXH64_canonical_t; 240 | XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash); 241 | XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src); 242 | #endif /* XXH_NO_LONG_LONG */ 243 | 244 | 245 | 246 | #ifdef XXH_STATIC_LINKING_ONLY 247 | 248 | /* ================================================================================================ 249 | This section contains declarations which are not guaranteed to remain stable. 250 | They may change in future versions, becoming incompatible with a different version of the library. 251 | These declarations should only be used with static linking. 252 | Never use them in association with dynamic linking ! 253 | =================================================================================================== */ 254 | 255 | /* These definitions are only present to allow 256 | * static allocation of XXH state, on stack or in a struct for example. 257 | * Never **ever** use members directly. */ 258 | 259 | #if !defined (__VMS) \ 260 | && (defined (__cplusplus) \ 261 | || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) 262 | # include 263 | 264 | struct XXH32_state_s { 265 | uint32_t total_len_32; 266 | uint32_t large_len; 267 | uint32_t v1; 268 | uint32_t v2; 269 | uint32_t v3; 270 | uint32_t v4; 271 | uint32_t mem32[4]; 272 | uint32_t memsize; 273 | uint32_t reserved; /* never read nor write, might be removed in a future version */ 274 | }; /* typedef'd to XXH32_state_t */ 275 | 276 | struct XXH64_state_s { 277 | uint64_t total_len; 278 | uint64_t v1; 279 | uint64_t v2; 280 | uint64_t v3; 281 | uint64_t v4; 282 | uint64_t mem64[4]; 283 | uint32_t memsize; 284 | uint32_t reserved[2]; /* never read nor write, might be removed in a future version */ 285 | }; /* typedef'd to XXH64_state_t */ 286 | 287 | # else 288 | 289 | struct XXH32_state_s { 290 | unsigned total_len_32; 291 | unsigned large_len; 292 | unsigned v1; 293 | unsigned v2; 294 | unsigned v3; 295 | unsigned v4; 296 | unsigned mem32[4]; 297 | unsigned memsize; 298 | unsigned reserved; /* never read nor write, might be removed in a future version */ 299 | }; /* typedef'd to XXH32_state_t */ 300 | 301 | # ifndef XXH_NO_LONG_LONG /* remove 64-bit support */ 302 | struct XXH64_state_s { 303 | unsigned long long total_len; 304 | unsigned long long v1; 305 | unsigned long long v2; 306 | unsigned long long v3; 307 | unsigned long long v4; 308 | unsigned long long mem64[4]; 309 | unsigned memsize; 310 | unsigned reserved[2]; /* never read nor write, might be removed in a future version */ 311 | }; /* typedef'd to XXH64_state_t */ 312 | # endif 313 | 314 | # endif 315 | 316 | 317 | #if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) 318 | # include "xxhash.c" /* include xxhash function bodies as `static`, for inlining */ 319 | #endif 320 | 321 | #endif /* XXH_STATIC_LINKING_ONLY */ 322 | 323 | 324 | #if defined (__cplusplus) 325 | } 326 | #endif 327 | 328 | #endif /* XXHASH_H_5627135585666179 */ 329 | -------------------------------------------------------------------------------- /libudis86/udis86.c: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/udis86.c 2 | * 3 | * Copyright (c) 2002-2013 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #include 28 | 29 | #include "udint.h" 30 | #include "extern.h" 31 | #include "decode.h" 32 | 33 | #if !defined(__UD_STANDALONE__) 34 | # if HAVE_STRING_H 35 | # include 36 | # endif 37 | #endif /* !__UD_STANDALONE__ */ 38 | 39 | static void ud_inp_init(struct ud *u); 40 | 41 | /* ============================================================================= 42 | * ud_init 43 | * Initializes ud_t object. 44 | * ============================================================================= 45 | */ 46 | extern void 47 | ud_init(struct ud* u) 48 | { 49 | memset((void*)u, 0, sizeof(struct ud)); 50 | ud_set_mode(u, 16); 51 | u->mnemonic = UD_Iinvalid; 52 | ud_set_pc(u, 0); 53 | #ifndef __UD_STANDALONE__ 54 | ud_set_input_file(u, stdin); 55 | #endif /* __UD_STANDALONE__ */ 56 | 57 | ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int)); 58 | } 59 | 60 | 61 | /* ============================================================================= 62 | * ud_disassemble 63 | * Disassembles one instruction and returns the number of 64 | * bytes disassembled. A zero means end of disassembly. 65 | * ============================================================================= 66 | */ 67 | extern unsigned int 68 | ud_disassemble(struct ud* u) 69 | { 70 | int len; 71 | if (u->inp_end) { 72 | return 0; 73 | } 74 | if ((len = ud_decode(u)) > 0) { 75 | if (u->translator != NULL) { 76 | u->asm_buf[0] = '\0'; 77 | u->translator(u); 78 | } 79 | } 80 | return len; 81 | } 82 | 83 | 84 | /* ============================================================================= 85 | * ud_set_mode() - Set Disassemly Mode. 86 | * ============================================================================= 87 | */ 88 | extern void 89 | ud_set_mode(struct ud* u, uint8_t m) 90 | { 91 | switch(m) { 92 | case 16: 93 | case 32: 94 | case 64: u->dis_mode = m ; return; 95 | default: u->dis_mode = 16; return; 96 | } 97 | } 98 | 99 | /* ============================================================================= 100 | * ud_set_vendor() - Set vendor. 101 | * ============================================================================= 102 | */ 103 | extern void 104 | ud_set_vendor(struct ud* u, unsigned v) 105 | { 106 | switch(v) { 107 | case UD_VENDOR_INTEL: 108 | u->vendor = v; 109 | break; 110 | case UD_VENDOR_ANY: 111 | u->vendor = v; 112 | break; 113 | default: 114 | u->vendor = UD_VENDOR_AMD; 115 | } 116 | } 117 | 118 | /* ============================================================================= 119 | * ud_set_pc() - Sets code origin. 120 | * ============================================================================= 121 | */ 122 | extern void 123 | ud_set_pc(struct ud* u, uint64_t o) 124 | { 125 | u->pc = o; 126 | } 127 | 128 | /* ============================================================================= 129 | * ud_set_syntax() - Sets the output syntax. 130 | * ============================================================================= 131 | */ 132 | extern void 133 | ud_set_syntax(struct ud* u, void (*t)(struct ud*)) 134 | { 135 | u->translator = t; 136 | } 137 | 138 | /* ============================================================================= 139 | * ud_insn() - returns the disassembled instruction 140 | * ============================================================================= 141 | */ 142 | const char* 143 | ud_insn_asm(const struct ud* u) 144 | { 145 | return u->asm_buf; 146 | } 147 | 148 | /* ============================================================================= 149 | * ud_insn_offset() - Returns the offset. 150 | * ============================================================================= 151 | */ 152 | uint64_t 153 | ud_insn_off(const struct ud* u) 154 | { 155 | return u->insn_offset; 156 | } 157 | 158 | 159 | /* ============================================================================= 160 | * ud_insn_hex() - Returns hex form of disassembled instruction. 161 | * ============================================================================= 162 | */ 163 | const char* 164 | ud_insn_hex(struct ud* u) 165 | { 166 | u->insn_hexcode[0] = 0; 167 | if (!u->error) { 168 | unsigned int i; 169 | const unsigned char *src_ptr = ud_insn_ptr(u); 170 | char* src_hex; 171 | src_hex = (char*) u->insn_hexcode; 172 | /* for each byte used to decode instruction */ 173 | for (i = 0; i < ud_insn_len(u) && i < sizeof(u->insn_hexcode) / 2; 174 | ++i, ++src_ptr) { 175 | sprintf(src_hex, "%02x", *src_ptr & 0xFF); 176 | src_hex += 2; 177 | } 178 | } 179 | return u->insn_hexcode; 180 | } 181 | 182 | 183 | /* ============================================================================= 184 | * ud_insn_ptr 185 | * Returns a pointer to buffer containing the bytes that were 186 | * disassembled. 187 | * ============================================================================= 188 | */ 189 | extern const uint8_t* 190 | ud_insn_ptr(const struct ud* u) 191 | { 192 | return (u->inp_buf == NULL) ? 193 | u->inp_sess : u->inp_buf + (u->inp_buf_index - u->inp_ctr); 194 | } 195 | 196 | 197 | /* ============================================================================= 198 | * ud_insn_len 199 | * Returns the count of bytes disassembled. 200 | * ============================================================================= 201 | */ 202 | extern unsigned int 203 | ud_insn_len(const struct ud* u) 204 | { 205 | return u->inp_ctr; 206 | } 207 | 208 | 209 | /* ============================================================================= 210 | * ud_insn_get_opr 211 | * Return the operand struct representing the nth operand of 212 | * the currently disassembled instruction. Returns NULL if 213 | * there's no such operand. 214 | * ============================================================================= 215 | */ 216 | const struct ud_operand* 217 | ud_insn_opr(const struct ud *u, unsigned int n) 218 | { 219 | if (n > 2 || u->operand[n].type == UD_NONE) { 220 | return NULL; 221 | } else { 222 | return &u->operand[n]; 223 | } 224 | } 225 | 226 | 227 | /* ============================================================================= 228 | * ud_opr_is_sreg 229 | * Returns non-zero if the given operand is of a segment register type. 230 | * ============================================================================= 231 | */ 232 | int 233 | ud_opr_is_sreg(const struct ud_operand *opr) 234 | { 235 | return opr->type == UD_OP_REG && 236 | opr->base >= UD_R_ES && 237 | opr->base <= UD_R_GS; 238 | } 239 | 240 | 241 | /* ============================================================================= 242 | * ud_opr_is_sreg 243 | * Returns non-zero if the given operand is of a general purpose 244 | * register type. 245 | * ============================================================================= 246 | */ 247 | int 248 | ud_opr_is_gpr(const struct ud_operand *opr) 249 | { 250 | return opr->type == UD_OP_REG && 251 | opr->base >= UD_R_AL && 252 | opr->base <= UD_R_R15; 253 | } 254 | 255 | 256 | /* ============================================================================= 257 | * ud_set_user_opaque_data 258 | * ud_get_user_opaque_data 259 | * Get/set user opaqute data pointer 260 | * ============================================================================= 261 | */ 262 | void 263 | ud_set_user_opaque_data(struct ud * u, void* opaque) 264 | { 265 | u->user_opaque_data = opaque; 266 | } 267 | 268 | void* 269 | ud_get_user_opaque_data(const struct ud *u) 270 | { 271 | return u->user_opaque_data; 272 | } 273 | 274 | 275 | /* ============================================================================= 276 | * ud_set_asm_buffer 277 | * Allow the user to set an assembler output buffer. If `buf` is NULL, 278 | * we switch back to the internal buffer. 279 | * ============================================================================= 280 | */ 281 | void 282 | ud_set_asm_buffer(struct ud *u, char *buf, size_t size) 283 | { 284 | if (buf == NULL) { 285 | ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int)); 286 | } else { 287 | u->asm_buf = buf; 288 | u->asm_buf_size = size; 289 | } 290 | } 291 | 292 | 293 | /* ============================================================================= 294 | * ud_set_sym_resolver 295 | * Set symbol resolver for relative targets used in the translation 296 | * phase. 297 | * 298 | * The resolver is a function that takes a uint64_t address and returns a 299 | * symbolic name for the that address. The function also takes a second 300 | * argument pointing to an integer that the client can optionally set to a 301 | * non-zero value for offsetted targets. (symbol+offset) The function may 302 | * also return NULL, in which case the translator only prints the target 303 | * address. 304 | * 305 | * The function pointer maybe NULL which resets symbol resolution. 306 | * ============================================================================= 307 | */ 308 | void 309 | ud_set_sym_resolver(struct ud *u, const char* (*resolver)(struct ud*, 310 | uint64_t addr, 311 | int64_t *offset)) 312 | { 313 | u->sym_resolver = resolver; 314 | } 315 | 316 | 317 | /* ============================================================================= 318 | * ud_insn_mnemonic 319 | * Return the current instruction mnemonic. 320 | * ============================================================================= 321 | */ 322 | enum ud_mnemonic_code 323 | ud_insn_mnemonic(const struct ud *u) 324 | { 325 | return u->mnemonic; 326 | } 327 | 328 | 329 | /* ============================================================================= 330 | * ud_lookup_mnemonic 331 | * Looks up mnemonic code in the mnemonic string table. 332 | * Returns NULL if the mnemonic code is invalid. 333 | * ============================================================================= 334 | */ 335 | const char* 336 | ud_lookup_mnemonic(enum ud_mnemonic_code c) 337 | { 338 | if (c < UD_MAX_MNEMONIC_CODE) { 339 | return ud_mnemonics_str[c]; 340 | } else { 341 | return NULL; 342 | } 343 | } 344 | 345 | 346 | /* 347 | * ud_inp_init 348 | * Initializes the input system. 349 | */ 350 | static void 351 | ud_inp_init(struct ud *u) 352 | { 353 | u->inp_hook = NULL; 354 | u->inp_buf = NULL; 355 | u->inp_buf_size = 0; 356 | u->inp_buf_index = 0; 357 | u->inp_curr = 0; 358 | u->inp_ctr = 0; 359 | u->inp_end = 0; 360 | UD_NON_STANDALONE(u->inp_file = NULL); 361 | } 362 | 363 | 364 | /* ============================================================================= 365 | * ud_inp_set_hook 366 | * Sets input hook. 367 | * ============================================================================= 368 | */ 369 | void 370 | ud_set_input_hook(register struct ud* u, int (*hook)(struct ud*)) 371 | { 372 | ud_inp_init(u); 373 | u->inp_hook = hook; 374 | } 375 | 376 | /* ============================================================================= 377 | * ud_inp_set_buffer 378 | * Set buffer as input. 379 | * ============================================================================= 380 | */ 381 | void 382 | ud_set_input_buffer(register struct ud* u, const uint8_t* buf, size_t len) 383 | { 384 | ud_inp_init(u); 385 | u->inp_buf = buf; 386 | u->inp_buf_size = len; 387 | u->inp_buf_index = 0; 388 | } 389 | 390 | 391 | #ifndef __UD_STANDALONE__ 392 | /* ============================================================================= 393 | * ud_input_set_file 394 | * Set FILE as input. 395 | * ============================================================================= 396 | */ 397 | static int 398 | inp_file_hook(struct ud* u) 399 | { 400 | return fgetc(u->inp_file); 401 | } 402 | 403 | void 404 | ud_set_input_file(register struct ud* u, FILE* f) 405 | { 406 | ud_inp_init(u); 407 | u->inp_hook = inp_file_hook; 408 | u->inp_file = f; 409 | } 410 | #endif /* __UD_STANDALONE__ */ 411 | 412 | 413 | /* ============================================================================= 414 | * ud_input_skip 415 | * Skip n input bytes. 416 | * ============================================================================ 417 | */ 418 | void 419 | ud_input_skip(struct ud* u, size_t n) 420 | { 421 | if (u->inp_end) { 422 | return; 423 | } 424 | if (u->inp_buf == NULL) { 425 | while (n--) { 426 | int c = u->inp_hook(u); 427 | if (c == UD_EOI) { 428 | goto eoi; 429 | } 430 | } 431 | return; 432 | } else { 433 | if (n > u->inp_buf_size || 434 | u->inp_buf_index > u->inp_buf_size - n) { 435 | u->inp_buf_index = u->inp_buf_size; 436 | goto eoi; 437 | } 438 | u->inp_buf_index += n; 439 | return; 440 | } 441 | eoi: 442 | u->inp_end = 1; 443 | UDERR(u, "cannot skip, eoi received\b"); 444 | return; 445 | } 446 | 447 | 448 | /* ============================================================================= 449 | * ud_input_end 450 | * Returns non-zero on end-of-input. 451 | * ============================================================================= 452 | */ 453 | int 454 | ud_input_end(const struct ud *u) 455 | { 456 | return u->inp_end; 457 | } 458 | 459 | /* vim:set ts=2 sw=2 expandtab */ 460 | -------------------------------------------------------------------------------- /libudis86/decode.c: -------------------------------------------------------------------------------- 1 | /* udis86 - libudis86/decode.c 2 | * 3 | * Copyright (c) 2002-2009 Vivek Thampi 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without modification, 7 | * are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #include "udint.h" 27 | #include "types.h" 28 | #include "decode.h" 29 | 30 | #ifndef __UD_STANDALONE__ 31 | # include 32 | #endif /* __UD_STANDALONE__ */ 33 | 34 | /* The max number of prefixes to an instruction */ 35 | #define MAX_PREFIXES 15 36 | 37 | /* rex prefix bits */ 38 | #define REX_W(r) ( ( 0xF & ( r ) ) >> 3 ) 39 | #define REX_R(r) ( ( 0x7 & ( r ) ) >> 2 ) 40 | #define REX_X(r) ( ( 0x3 & ( r ) ) >> 1 ) 41 | #define REX_B(r) ( ( 0x1 & ( r ) ) >> 0 ) 42 | #define REX_PFX_MASK(n) ( ( P_REXW(n) << 3 ) | \ 43 | ( P_REXR(n) << 2 ) | \ 44 | ( P_REXX(n) << 1 ) | \ 45 | ( P_REXB(n) << 0 ) ) 46 | 47 | /* scable-index-base bits */ 48 | #define SIB_S(b) ( ( b ) >> 6 ) 49 | #define SIB_I(b) ( ( ( b ) >> 3 ) & 7 ) 50 | #define SIB_B(b) ( ( b ) & 7 ) 51 | 52 | /* modrm bits */ 53 | #define MODRM_REG(b) ( ( ( b ) >> 3 ) & 7 ) 54 | #define MODRM_NNN(b) ( ( ( b ) >> 3 ) & 7 ) 55 | #define MODRM_MOD(b) ( ( ( b ) >> 6 ) & 3 ) 56 | #define MODRM_RM(b) ( ( b ) & 7 ) 57 | 58 | static int decode_ext(struct ud *u, uint16_t ptr); 59 | 60 | enum reg_class { /* register classes */ 61 | REGCLASS_GPR, 62 | REGCLASS_MMX, 63 | REGCLASS_CR, 64 | REGCLASS_DB, 65 | REGCLASS_SEG, 66 | REGCLASS_XMM 67 | }; 68 | 69 | /* 70 | * inp_start 71 | * Should be called before each de-code operation. 72 | */ 73 | static void 74 | inp_start(struct ud *u) 75 | { 76 | u->inp_ctr = 0; 77 | } 78 | 79 | 80 | static uint8_t 81 | inp_next(struct ud *u) 82 | { 83 | if (u->inp_end == 0) { 84 | if (u->inp_buf != NULL) { 85 | if (u->inp_buf_index < u->inp_buf_size) { 86 | u->inp_ctr++; 87 | return (u->inp_curr = u->inp_buf[u->inp_buf_index++]); 88 | } 89 | } else { 90 | int c; 91 | if ((c = u->inp_hook(u)) != UD_EOI) { 92 | u->inp_curr = c; 93 | u->inp_sess[u->inp_ctr++] = u->inp_curr; 94 | return u->inp_curr; 95 | } 96 | } 97 | } 98 | u->inp_end = 1; 99 | UDERR(u, "byte expected, eoi received\n"); 100 | return 0; 101 | } 102 | 103 | static uint8_t 104 | inp_curr(struct ud *u) 105 | { 106 | return u->inp_curr; 107 | } 108 | 109 | 110 | /* 111 | * inp_uint8 112 | * int_uint16 113 | * int_uint32 114 | * int_uint64 115 | * Load little-endian values from input 116 | */ 117 | static uint8_t 118 | inp_uint8(struct ud* u) 119 | { 120 | return inp_next(u); 121 | } 122 | 123 | static uint16_t 124 | inp_uint16(struct ud* u) 125 | { 126 | uint16_t r, ret; 127 | 128 | ret = inp_next(u); 129 | r = inp_next(u); 130 | return ret | (r << 8); 131 | } 132 | 133 | static uint32_t 134 | inp_uint32(struct ud* u) 135 | { 136 | uint32_t r, ret; 137 | 138 | ret = inp_next(u); 139 | r = inp_next(u); 140 | ret = ret | (r << 8); 141 | r = inp_next(u); 142 | ret = ret | (r << 16); 143 | r = inp_next(u); 144 | return ret | (r << 24); 145 | } 146 | 147 | static uint64_t 148 | inp_uint64(struct ud* u) 149 | { 150 | uint64_t r, ret; 151 | 152 | ret = inp_next(u); 153 | r = inp_next(u); 154 | ret = ret | (r << 8); 155 | r = inp_next(u); 156 | ret = ret | (r << 16); 157 | r = inp_next(u); 158 | ret = ret | (r << 24); 159 | r = inp_next(u); 160 | ret = ret | (r << 32); 161 | r = inp_next(u); 162 | ret = ret | (r << 40); 163 | r = inp_next(u); 164 | ret = ret | (r << 48); 165 | r = inp_next(u); 166 | return ret | (r << 56); 167 | } 168 | 169 | 170 | static inline int 171 | eff_opr_mode(int dis_mode, int rex_w, int pfx_opr) 172 | { 173 | if (dis_mode == 64) { 174 | return rex_w ? 64 : (pfx_opr ? 16 : 32); 175 | } else if (dis_mode == 32) { 176 | return pfx_opr ? 16 : 32; 177 | } else { 178 | UD_ASSERT(dis_mode == 16); 179 | return pfx_opr ? 32 : 16; 180 | } 181 | } 182 | 183 | 184 | static inline int 185 | eff_adr_mode(int dis_mode, int pfx_adr) 186 | { 187 | if (dis_mode == 64) { 188 | return pfx_adr ? 32 : 64; 189 | } else if (dis_mode == 32) { 190 | return pfx_adr ? 16 : 32; 191 | } else { 192 | UD_ASSERT(dis_mode == 16); 193 | return pfx_adr ? 32 : 16; 194 | } 195 | } 196 | 197 | 198 | /* 199 | * decode_prefixes 200 | * 201 | * Extracts instruction prefixes. 202 | */ 203 | static int 204 | decode_prefixes(struct ud *u) 205 | { 206 | int done = 0; 207 | uint8_t curr, last = 0; 208 | UD_RETURN_ON_ERROR(u); 209 | 210 | do { 211 | last = curr; 212 | curr = inp_next(u); 213 | UD_RETURN_ON_ERROR(u); 214 | if (u->inp_ctr == MAX_INSN_LENGTH) { 215 | UD_RETURN_WITH_ERROR(u, "max instruction length"); 216 | } 217 | 218 | switch (curr) 219 | { 220 | case 0x2E: 221 | u->pfx_seg = UD_R_CS; 222 | break; 223 | case 0x36: 224 | u->pfx_seg = UD_R_SS; 225 | break; 226 | case 0x3E: 227 | u->pfx_seg = UD_R_DS; 228 | break; 229 | case 0x26: 230 | u->pfx_seg = UD_R_ES; 231 | break; 232 | case 0x64: 233 | u->pfx_seg = UD_R_FS; 234 | break; 235 | case 0x65: 236 | u->pfx_seg = UD_R_GS; 237 | break; 238 | case 0x67: /* adress-size override prefix */ 239 | u->pfx_adr = 0x67; 240 | break; 241 | case 0xF0: 242 | u->pfx_lock = 0xF0; 243 | break; 244 | case 0x66: 245 | u->pfx_opr = 0x66; 246 | break; 247 | case 0xF2: 248 | u->pfx_str = 0xf2; 249 | break; 250 | case 0xF3: 251 | u->pfx_str = 0xf3; 252 | break; 253 | default: 254 | /* consume if rex */ 255 | done = (u->dis_mode == 64 && (curr & 0xF0) == 0x40) ? 0 : 1; 256 | break; 257 | } 258 | } while (!done); 259 | /* rex prefixes in 64bit mode, must be the last prefix */ 260 | if (u->dis_mode == 64 && (last & 0xF0) == 0x40) { 261 | u->pfx_rex = last; 262 | } 263 | return 0; 264 | } 265 | 266 | 267 | static inline unsigned int modrm( struct ud * u ) 268 | { 269 | if ( !u->have_modrm ) { 270 | u->modrm = inp_next( u ); 271 | u->have_modrm = 1; 272 | } 273 | return u->modrm; 274 | } 275 | 276 | 277 | static unsigned int 278 | resolve_operand_size( const struct ud * u, unsigned int s ) 279 | { 280 | switch ( s ) 281 | { 282 | case SZ_V: 283 | return ( u->opr_mode ); 284 | case SZ_Z: 285 | return ( u->opr_mode == 16 ) ? 16 : 32; 286 | case SZ_Y: 287 | return ( u->opr_mode == 16 ) ? 32 : u->opr_mode; 288 | case SZ_RDQ: 289 | return ( u->dis_mode == 64 ) ? 64 : 32; 290 | default: 291 | return s; 292 | } 293 | } 294 | 295 | 296 | static int resolve_mnemonic( struct ud* u ) 297 | { 298 | /* resolve 3dnow weirdness. */ 299 | if ( u->mnemonic == UD_I3dnow ) { 300 | u->mnemonic = ud_itab[ u->le->table[ inp_curr( u ) ] ].mnemonic; 301 | } 302 | /* SWAPGS is only valid in 64bits mode */ 303 | if ( u->mnemonic == UD_Iswapgs && u->dis_mode != 64 ) { 304 | UDERR(u, "swapgs invalid in 64bits mode\n"); 305 | return -1; 306 | } 307 | 308 | if (u->mnemonic == UD_Ixchg) { 309 | if ((u->operand[0].type == UD_OP_REG && u->operand[0].base == UD_R_AX && 310 | u->operand[1].type == UD_OP_REG && u->operand[1].base == UD_R_AX) || 311 | (u->operand[0].type == UD_OP_REG && u->operand[0].base == UD_R_EAX && 312 | u->operand[1].type == UD_OP_REG && u->operand[1].base == UD_R_EAX)) { 313 | u->operand[0].type = UD_NONE; 314 | u->operand[1].type = UD_NONE; 315 | u->mnemonic = UD_Inop; 316 | } 317 | } 318 | 319 | if (u->mnemonic == UD_Inop && u->pfx_repe) { 320 | u->pfx_repe = 0; 321 | u->mnemonic = UD_Ipause; 322 | } 323 | return 0; 324 | } 325 | 326 | 327 | /* ----------------------------------------------------------------------------- 328 | * decode_a()- Decodes operands of the type seg:offset 329 | * ----------------------------------------------------------------------------- 330 | */ 331 | static void 332 | decode_a(struct ud* u, struct ud_operand *op) 333 | { 334 | if (u->opr_mode == 16) { 335 | /* seg16:off16 */ 336 | op->type = UD_OP_PTR; 337 | op->size = 32; 338 | op->lval.ptr.off = inp_uint16(u); 339 | op->lval.ptr.seg = inp_uint16(u); 340 | } else { 341 | /* seg16:off32 */ 342 | op->type = UD_OP_PTR; 343 | op->size = 48; 344 | op->lval.ptr.off = inp_uint32(u); 345 | op->lval.ptr.seg = inp_uint16(u); 346 | } 347 | } 348 | 349 | /* ----------------------------------------------------------------------------- 350 | * decode_gpr() - Returns decoded General Purpose Register 351 | * ----------------------------------------------------------------------------- 352 | */ 353 | static enum ud_type 354 | decode_gpr(register struct ud* u, unsigned int s, unsigned char rm) 355 | { 356 | switch (s) { 357 | case 64: 358 | return UD_R_RAX + rm; 359 | case 32: 360 | return UD_R_EAX + rm; 361 | case 16: 362 | return UD_R_AX + rm; 363 | case 8: 364 | if (u->dis_mode == 64 && u->pfx_rex) { 365 | if (rm >= 4) 366 | return UD_R_SPL + (rm-4); 367 | return UD_R_AL + rm; 368 | } else return UD_R_AL + rm; 369 | case 0: 370 | /* invalid size in case of a decode error */ 371 | UD_ASSERT(u->error); 372 | return UD_NONE; 373 | default: 374 | UD_ASSERT(!"invalid operand size"); 375 | return UD_NONE; 376 | } 377 | } 378 | 379 | static void 380 | decode_reg(struct ud *u, 381 | struct ud_operand *opr, 382 | int type, 383 | int num, 384 | int size) 385 | { 386 | int reg; 387 | size = resolve_operand_size(u, size); 388 | switch (type) { 389 | case REGCLASS_GPR : reg = decode_gpr(u, size, num); break; 390 | case REGCLASS_MMX : reg = UD_R_MM0 + (num & 7); break; 391 | case REGCLASS_XMM : reg = UD_R_XMM0 + num; break; 392 | case REGCLASS_CR : reg = UD_R_CR0 + num; break; 393 | case REGCLASS_DB : reg = UD_R_DR0 + num; break; 394 | case REGCLASS_SEG : { 395 | /* 396 | * Only 6 segment registers, anything else is an error. 397 | */ 398 | if ((num & 7) > 5) { 399 | UDERR(u, "invalid segment register value\n"); 400 | return; 401 | } else { 402 | reg = UD_R_ES + (num & 7); 403 | } 404 | break; 405 | } 406 | default: 407 | UD_ASSERT(!"invalid register type"); 408 | return; 409 | } 410 | opr->type = UD_OP_REG; 411 | opr->base = reg; 412 | opr->size = size; 413 | } 414 | 415 | 416 | /* 417 | * decode_imm 418 | * 419 | * Decode Immediate values. 420 | */ 421 | static void 422 | decode_imm(struct ud* u, unsigned int size, struct ud_operand *op) 423 | { 424 | op->size = resolve_operand_size(u, size); 425 | op->type = UD_OP_IMM; 426 | 427 | switch (op->size) { 428 | case 8: op->lval.sbyte = inp_uint8(u); break; 429 | case 16: op->lval.uword = inp_uint16(u); break; 430 | case 32: op->lval.udword = inp_uint32(u); break; 431 | case 64: op->lval.uqword = inp_uint64(u); break; 432 | default: return; 433 | } 434 | } 435 | 436 | 437 | /* 438 | * decode_mem_disp 439 | * 440 | * Decode mem address displacement. 441 | */ 442 | static void 443 | decode_mem_disp(struct ud* u, unsigned int size, struct ud_operand *op) 444 | { 445 | switch (size) { 446 | case 8: 447 | op->offset = 8; 448 | op->lval.ubyte = inp_uint8(u); 449 | break; 450 | case 16: 451 | op->offset = 16; 452 | op->lval.uword = inp_uint16(u); 453 | break; 454 | case 32: 455 | op->offset = 32; 456 | op->lval.udword = inp_uint32(u); 457 | break; 458 | case 64: 459 | op->offset = 64; 460 | op->lval.uqword = inp_uint64(u); 461 | break; 462 | default: 463 | return; 464 | } 465 | } 466 | 467 | 468 | /* 469 | * decode_modrm_reg 470 | * 471 | * Decodes reg field of mod/rm byte 472 | * 473 | */ 474 | static inline void 475 | decode_modrm_reg(struct ud *u, 476 | struct ud_operand *operand, 477 | unsigned int type, 478 | unsigned int size) 479 | { 480 | uint8_t reg = (REX_R(u->pfx_rex) << 3) | MODRM_REG(modrm(u)); 481 | decode_reg(u, operand, type, reg, size); 482 | } 483 | 484 | 485 | /* 486 | * decode_modrm_rm 487 | * 488 | * Decodes rm field of mod/rm byte 489 | * 490 | */ 491 | static void 492 | decode_modrm_rm(struct ud *u, 493 | struct ud_operand *op, 494 | unsigned char type, /* register type */ 495 | unsigned int size) /* operand size */ 496 | 497 | { 498 | size_t offset = 0; 499 | unsigned char mod, rm; 500 | 501 | /* get mod, r/m and reg fields */ 502 | mod = MODRM_MOD(modrm(u)); 503 | rm = (REX_B(u->pfx_rex) << 3) | MODRM_RM(modrm(u)); 504 | 505 | /* 506 | * If mod is 11b, then the modrm.rm specifies a register. 507 | * 508 | */ 509 | if (mod == 3) { 510 | decode_reg(u, op, type, rm, size); 511 | return; 512 | } 513 | 514 | /* 515 | * !11b => Memory Address 516 | */ 517 | op->type = UD_OP_MEM; 518 | op->size = resolve_operand_size(u, size); 519 | 520 | if (u->adr_mode == 64) { 521 | op->base = UD_R_RAX + rm; 522 | if (mod == 1) { 523 | offset = 8; 524 | } else if (mod == 2) { 525 | offset = 32; 526 | } else if (mod == 0 && (rm & 7) == 5) { 527 | op->base = UD_R_RIP; 528 | offset = 32; 529 | } else { 530 | offset = 0; 531 | } 532 | /* 533 | * Scale-Index-Base (SIB) 534 | */ 535 | if ((rm & 7) == 4) { 536 | inp_next(u); 537 | 538 | op->scale = (1 << SIB_S(inp_curr(u))) & ~1; 539 | op->index = UD_R_RAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3)); 540 | op->base = UD_R_RAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3)); 541 | 542 | /* special conditions for base reference */ 543 | if (op->index == UD_R_RSP) { 544 | op->index = UD_NONE; 545 | op->scale = UD_NONE; 546 | } 547 | 548 | if (op->base == UD_R_RBP || op->base == UD_R_R13) { 549 | if (mod == 0) { 550 | op->base = UD_NONE; 551 | } 552 | if (mod == 1) { 553 | offset = 8; 554 | } else { 555 | offset = 32; 556 | } 557 | } 558 | } 559 | } else if (u->adr_mode == 32) { 560 | op->base = UD_R_EAX + rm; 561 | if (mod == 1) { 562 | offset = 8; 563 | } else if (mod == 2) { 564 | offset = 32; 565 | } else if (mod == 0 && rm == 5) { 566 | op->base = UD_NONE; 567 | offset = 32; 568 | } else { 569 | offset = 0; 570 | } 571 | 572 | /* Scale-Index-Base (SIB) */ 573 | if ((rm & 7) == 4) { 574 | inp_next(u); 575 | 576 | op->scale = (1 << SIB_S(inp_curr(u))) & ~1; 577 | op->index = UD_R_EAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3)); 578 | op->base = UD_R_EAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3)); 579 | 580 | if (op->index == UD_R_ESP) { 581 | op->index = UD_NONE; 582 | op->scale = UD_NONE; 583 | } 584 | 585 | /* special condition for base reference */ 586 | if (op->base == UD_R_EBP) { 587 | if (mod == 0) { 588 | op->base = UD_NONE; 589 | } 590 | if (mod == 1) { 591 | offset = 8; 592 | } else { 593 | offset = 32; 594 | } 595 | } 596 | } 597 | } else { 598 | const unsigned int bases[] = { UD_R_BX, UD_R_BX, UD_R_BP, UD_R_BP, 599 | UD_R_SI, UD_R_DI, UD_R_BP, UD_R_BX }; 600 | const unsigned int indices[] = { UD_R_SI, UD_R_DI, UD_R_SI, UD_R_DI, 601 | UD_NONE, UD_NONE, UD_NONE, UD_NONE }; 602 | op->base = bases[rm & 7]; 603 | op->index = indices[rm & 7]; 604 | if (mod == 0 && rm == 6) { 605 | offset = 16; 606 | op->base = UD_NONE; 607 | } else if (mod == 1) { 608 | offset = 8; 609 | } else if (mod == 2) { 610 | offset = 16; 611 | } 612 | } 613 | 614 | if (offset) { 615 | decode_mem_disp(u, offset, op); 616 | } 617 | } 618 | 619 | 620 | /* 621 | * decode_moffset 622 | * Decode offset-only memory operand 623 | */ 624 | static void 625 | decode_moffset(struct ud *u, unsigned int size, struct ud_operand *opr) 626 | { 627 | opr->type = UD_OP_MEM; 628 | opr->size = resolve_operand_size(u, size); 629 | decode_mem_disp(u, u->adr_mode, opr); 630 | } 631 | 632 | 633 | /* ----------------------------------------------------------------------------- 634 | * decode_operands() - Disassembles Operands. 635 | * ----------------------------------------------------------------------------- 636 | */ 637 | static int 638 | decode_operand(struct ud *u, 639 | struct ud_operand *operand, 640 | enum ud_operand_code type, 641 | unsigned int size) 642 | { 643 | operand->_oprcode = type; 644 | 645 | switch (type) { 646 | case OP_A : 647 | decode_a(u, operand); 648 | break; 649 | case OP_MR: 650 | decode_modrm_rm(u, operand, REGCLASS_GPR, 651 | MODRM_MOD(modrm(u)) == 3 ? 652 | Mx_reg_size(size) : Mx_mem_size(size)); 653 | break; 654 | case OP_F: 655 | u->br_far = 1; 656 | /* intended fall through */ 657 | case OP_M: 658 | if (MODRM_MOD(modrm(u)) == 3) { 659 | UDERR(u, "expected modrm.mod != 3\n"); 660 | } 661 | /* intended fall through */ 662 | case OP_E: 663 | decode_modrm_rm(u, operand, REGCLASS_GPR, size); 664 | break; 665 | case OP_G: 666 | decode_modrm_reg(u, operand, REGCLASS_GPR, size); 667 | break; 668 | case OP_sI: 669 | case OP_I: 670 | decode_imm(u, size, operand); 671 | break; 672 | case OP_I1: 673 | operand->type = UD_OP_CONST; 674 | operand->lval.udword = 1; 675 | break; 676 | case OP_N: 677 | if (MODRM_MOD(modrm(u)) != 3) { 678 | UDERR(u, "expected modrm.mod == 3\n"); 679 | } 680 | /* intended fall through */ 681 | case OP_Q: 682 | decode_modrm_rm(u, operand, REGCLASS_MMX, size); 683 | break; 684 | case OP_P: 685 | decode_modrm_reg(u, operand, REGCLASS_MMX, size); 686 | break; 687 | case OP_U: 688 | if (MODRM_MOD(modrm(u)) != 3) { 689 | UDERR(u, "expected modrm.mod == 3\n"); 690 | } 691 | /* intended fall through */ 692 | case OP_W: 693 | decode_modrm_rm(u, operand, REGCLASS_XMM, size); 694 | break; 695 | case OP_V: 696 | decode_modrm_reg(u, operand, REGCLASS_XMM, size); 697 | break; 698 | case OP_MU: 699 | decode_modrm_rm(u, operand, REGCLASS_XMM, 700 | MODRM_MOD(modrm(u)) == 3 ? 701 | Mx_reg_size(size) : Mx_mem_size(size)); 702 | break; 703 | case OP_S: 704 | decode_modrm_reg(u, operand, REGCLASS_SEG, size); 705 | break; 706 | case OP_O: 707 | decode_moffset(u, size, operand); 708 | break; 709 | case OP_R0: 710 | case OP_R1: 711 | case OP_R2: 712 | case OP_R3: 713 | case OP_R4: 714 | case OP_R5: 715 | case OP_R6: 716 | case OP_R7: 717 | decode_reg(u, operand, REGCLASS_GPR, 718 | (REX_B(u->pfx_rex) << 3) | (type - OP_R0), size); 719 | break; 720 | case OP_AL: 721 | case OP_AX: 722 | case OP_eAX: 723 | case OP_rAX: 724 | decode_reg(u, operand, REGCLASS_GPR, 0, size); 725 | break; 726 | case OP_CL: 727 | case OP_CX: 728 | case OP_eCX: 729 | decode_reg(u, operand, REGCLASS_GPR, 1, size); 730 | break; 731 | case OP_DL: 732 | case OP_DX: 733 | case OP_eDX: 734 | decode_reg(u, operand, REGCLASS_GPR, 2, size); 735 | break; 736 | case OP_ES: 737 | case OP_CS: 738 | case OP_DS: 739 | case OP_SS: 740 | case OP_FS: 741 | case OP_GS: 742 | /* in 64bits mode, only fs and gs are allowed */ 743 | if (u->dis_mode == 64) { 744 | if (type != OP_FS && type != OP_GS) { 745 | UDERR(u, "invalid segment register in 64bits\n"); 746 | } 747 | } 748 | operand->type = UD_OP_REG; 749 | operand->base = (type - OP_ES) + UD_R_ES; 750 | operand->size = 16; 751 | break; 752 | case OP_J : 753 | decode_imm(u, size, operand); 754 | operand->type = UD_OP_JIMM; 755 | break ; 756 | case OP_R : 757 | if (MODRM_MOD(modrm(u)) != 3) { 758 | UDERR(u, "expected modrm.mod == 3\n"); 759 | } 760 | decode_modrm_rm(u, operand, REGCLASS_GPR, size); 761 | break; 762 | case OP_C: 763 | decode_modrm_reg(u, operand, REGCLASS_CR, size); 764 | break; 765 | case OP_D: 766 | decode_modrm_reg(u, operand, REGCLASS_DB, size); 767 | break; 768 | case OP_I3 : 769 | operand->type = UD_OP_CONST; 770 | operand->lval.sbyte = 3; 771 | break; 772 | case OP_ST0: 773 | case OP_ST1: 774 | case OP_ST2: 775 | case OP_ST3: 776 | case OP_ST4: 777 | case OP_ST5: 778 | case OP_ST6: 779 | case OP_ST7: 780 | operand->type = UD_OP_REG; 781 | operand->base = (type - OP_ST0) + UD_R_ST0; 782 | operand->size = 80; 783 | break; 784 | default : 785 | break; 786 | } 787 | return 0; 788 | } 789 | 790 | 791 | /* 792 | * decode_operands 793 | * 794 | * Disassemble upto 3 operands of the current instruction being 795 | * disassembled. By the end of the function, the operand fields 796 | * of the ud structure will have been filled. 797 | */ 798 | static int 799 | decode_operands(struct ud* u) 800 | { 801 | decode_operand(u, &u->operand[0], 802 | u->itab_entry->operand1.type, 803 | u->itab_entry->operand1.size); 804 | decode_operand(u, &u->operand[1], 805 | u->itab_entry->operand2.type, 806 | u->itab_entry->operand2.size); 807 | decode_operand(u, &u->operand[2], 808 | u->itab_entry->operand3.type, 809 | u->itab_entry->operand3.size); 810 | return 0; 811 | } 812 | 813 | /* ----------------------------------------------------------------------------- 814 | * clear_insn() - clear instruction structure 815 | * ----------------------------------------------------------------------------- 816 | */ 817 | static void 818 | clear_insn(register struct ud* u) 819 | { 820 | u->error = 0; 821 | u->pfx_seg = 0; 822 | u->pfx_opr = 0; 823 | u->pfx_adr = 0; 824 | u->pfx_lock = 0; 825 | u->pfx_repne = 0; 826 | u->pfx_rep = 0; 827 | u->pfx_repe = 0; 828 | u->pfx_rex = 0; 829 | u->pfx_str = 0; 830 | u->mnemonic = UD_Inone; 831 | u->itab_entry = NULL; 832 | u->have_modrm = 0; 833 | u->br_far = 0; 834 | 835 | memset( &u->operand[ 0 ], 0, sizeof( struct ud_operand ) ); 836 | memset( &u->operand[ 1 ], 0, sizeof( struct ud_operand ) ); 837 | memset( &u->operand[ 2 ], 0, sizeof( struct ud_operand ) ); 838 | } 839 | 840 | 841 | static inline int 842 | resolve_pfx_str(struct ud* u) 843 | { 844 | if (u->pfx_str == 0xf3) { 845 | if (P_STR(u->itab_entry->prefix)) { 846 | u->pfx_rep = 0xf3; 847 | } else { 848 | u->pfx_repe = 0xf3; 849 | } 850 | } else if (u->pfx_str == 0xf2) { 851 | u->pfx_repne = 0xf3; 852 | } 853 | return 0; 854 | } 855 | 856 | 857 | static int 858 | resolve_mode( struct ud* u ) 859 | { 860 | int default64; 861 | /* if in error state, bail out */ 862 | if ( u->error ) return -1; 863 | 864 | /* propagate prefix effects */ 865 | if ( u->dis_mode == 64 ) { /* set 64bit-mode flags */ 866 | 867 | /* Check validity of instruction m64 */ 868 | if ( P_INV64( u->itab_entry->prefix ) ) { 869 | UDERR(u, "instruction invalid in 64bits\n"); 870 | return -1; 871 | } 872 | 873 | /* effective rex prefix is the effective mask for the 874 | * instruction hard-coded in the opcode map. 875 | */ 876 | u->pfx_rex = ( u->pfx_rex & 0x40 ) | 877 | ( u->pfx_rex & REX_PFX_MASK( u->itab_entry->prefix ) ); 878 | 879 | /* whether this instruction has a default operand size of 880 | * 64bit, also hardcoded into the opcode map. 881 | */ 882 | default64 = P_DEF64( u->itab_entry->prefix ); 883 | /* calculate effective operand size */ 884 | if ( REX_W( u->pfx_rex ) ) { 885 | u->opr_mode = 64; 886 | } else if ( u->pfx_opr ) { 887 | u->opr_mode = 16; 888 | } else { 889 | /* unless the default opr size of instruction is 64, 890 | * the effective operand size in the absence of rex.w 891 | * prefix is 32. 892 | */ 893 | u->opr_mode = default64 ? 64 : 32; 894 | } 895 | 896 | /* calculate effective address size */ 897 | u->adr_mode = (u->pfx_adr) ? 32 : 64; 898 | } else if ( u->dis_mode == 32 ) { /* set 32bit-mode flags */ 899 | u->opr_mode = ( u->pfx_opr ) ? 16 : 32; 900 | u->adr_mode = ( u->pfx_adr ) ? 16 : 32; 901 | } else if ( u->dis_mode == 16 ) { /* set 16bit-mode flags */ 902 | u->opr_mode = ( u->pfx_opr ) ? 32 : 16; 903 | u->adr_mode = ( u->pfx_adr ) ? 32 : 16; 904 | } 905 | 906 | return 0; 907 | } 908 | 909 | 910 | static inline int 911 | decode_insn(struct ud *u, uint16_t ptr) 912 | { 913 | UD_ASSERT((ptr & 0x8000) == 0); 914 | u->itab_entry = &ud_itab[ ptr ]; 915 | u->mnemonic = u->itab_entry->mnemonic; 916 | return (resolve_pfx_str(u) == 0 && 917 | resolve_mode(u) == 0 && 918 | decode_operands(u) == 0 && 919 | resolve_mnemonic(u) == 0) ? 0 : -1; 920 | } 921 | 922 | 923 | /* 924 | * decode_3dnow() 925 | * 926 | * Decoding 3dnow is a little tricky because of its strange opcode 927 | * structure. The final opcode disambiguation depends on the last 928 | * byte that comes after the operands have been decoded. Fortunately, 929 | * all 3dnow instructions have the same set of operand types. So we 930 | * go ahead and decode the instruction by picking an arbitrarily chosen 931 | * valid entry in the table, decode the operands, and read the final 932 | * byte to resolve the menmonic. 933 | */ 934 | static inline int 935 | decode_3dnow(struct ud* u) 936 | { 937 | uint16_t ptr; 938 | UD_ASSERT(u->le->type == UD_TAB__OPC_3DNOW); 939 | UD_ASSERT(u->le->table[0xc] != 0); 940 | decode_insn(u, u->le->table[0xc]); 941 | inp_next(u); 942 | if (u->error) { 943 | return -1; 944 | } 945 | ptr = u->le->table[inp_curr(u)]; 946 | UD_ASSERT((ptr & 0x8000) == 0); 947 | u->mnemonic = ud_itab[ptr].mnemonic; 948 | return 0; 949 | } 950 | 951 | 952 | static int 953 | decode_ssepfx(struct ud *u) 954 | { 955 | uint8_t idx; 956 | uint8_t pfx; 957 | 958 | /* 959 | * String prefixes (f2, f3) take precedence over operand 960 | * size prefix (66). 961 | */ 962 | pfx = u->pfx_str; 963 | if (pfx == 0) { 964 | pfx = u->pfx_opr; 965 | } 966 | idx = ((pfx & 0xf) + 1) / 2; 967 | if (u->le->table[idx] == 0) { 968 | idx = 0; 969 | } 970 | if (idx && u->le->table[idx] != 0) { 971 | /* 972 | * "Consume" the prefix as a part of the opcode, so it is no 973 | * longer exported as an instruction prefix. 974 | */ 975 | u->pfx_str = 0; 976 | if (pfx == 0x66) { 977 | /* 978 | * consume "66" only if it was used for decoding, leaving 979 | * it to be used as an operands size override for some 980 | * simd instructions. 981 | */ 982 | u->pfx_opr = 0; 983 | } 984 | } 985 | return decode_ext(u, u->le->table[idx]); 986 | } 987 | 988 | 989 | /* 990 | * decode_ext() 991 | * 992 | * Decode opcode extensions (if any) 993 | */ 994 | static int 995 | decode_ext(struct ud *u, uint16_t ptr) 996 | { 997 | uint8_t idx = 0; 998 | if ((ptr & 0x8000) == 0) { 999 | return decode_insn(u, ptr); 1000 | } 1001 | u->le = &ud_lookup_table_list[(~0x8000 & ptr)]; 1002 | if (u->le->type == UD_TAB__OPC_3DNOW) { 1003 | return decode_3dnow(u); 1004 | } 1005 | 1006 | switch (u->le->type) { 1007 | case UD_TAB__OPC_MOD: 1008 | /* !11 = 0, 11 = 1 */ 1009 | idx = (MODRM_MOD(modrm(u)) + 1) / 4; 1010 | break; 1011 | /* disassembly mode/operand size/address size based tables. 1012 | * 16 = 0,, 32 = 1, 64 = 2 1013 | */ 1014 | case UD_TAB__OPC_MODE: 1015 | idx = u->dis_mode != 64 ? 0 : 1; 1016 | break; 1017 | case UD_TAB__OPC_OSIZE: 1018 | idx = eff_opr_mode(u->dis_mode, REX_W(u->pfx_rex), u->pfx_opr) / 32; 1019 | break; 1020 | case UD_TAB__OPC_ASIZE: 1021 | idx = eff_adr_mode(u->dis_mode, u->pfx_adr) / 32; 1022 | break; 1023 | case UD_TAB__OPC_X87: 1024 | idx = modrm(u) - 0xC0; 1025 | break; 1026 | case UD_TAB__OPC_VENDOR: 1027 | if (u->vendor == UD_VENDOR_ANY) { 1028 | /* choose a valid entry */ 1029 | idx = (u->le->table[idx] != 0) ? 0 : 1; 1030 | } else if (u->vendor == UD_VENDOR_AMD) { 1031 | idx = 0; 1032 | } else { 1033 | idx = 1; 1034 | } 1035 | break; 1036 | case UD_TAB__OPC_RM: 1037 | idx = MODRM_RM(modrm(u)); 1038 | break; 1039 | case UD_TAB__OPC_REG: 1040 | idx = MODRM_REG(modrm(u)); 1041 | break; 1042 | case UD_TAB__OPC_SSE: 1043 | return decode_ssepfx(u); 1044 | default: 1045 | UD_ASSERT(!"not reached"); 1046 | break; 1047 | } 1048 | 1049 | return decode_ext(u, u->le->table[idx]); 1050 | } 1051 | 1052 | 1053 | static int 1054 | decode_opcode(struct ud *u) 1055 | { 1056 | uint16_t ptr; 1057 | UD_ASSERT(u->le->type == UD_TAB__OPC_TABLE); 1058 | UD_RETURN_ON_ERROR(u); 1059 | u->primary_opcode = inp_curr(u); 1060 | ptr = u->le->table[inp_curr(u)]; 1061 | if (ptr & 0x8000) { 1062 | u->le = &ud_lookup_table_list[ptr & ~0x8000]; 1063 | if (u->le->type == UD_TAB__OPC_TABLE) { 1064 | inp_next(u); 1065 | return decode_opcode(u); 1066 | } 1067 | } 1068 | return decode_ext(u, ptr); 1069 | } 1070 | 1071 | 1072 | /* ============================================================================= 1073 | * ud_decode() - Instruction decoder. Returns the number of bytes decoded. 1074 | * ============================================================================= 1075 | */ 1076 | unsigned int 1077 | ud_decode(struct ud *u) 1078 | { 1079 | inp_start(u); 1080 | clear_insn(u); 1081 | u->le = &ud_lookup_table_list[0]; 1082 | u->error = decode_prefixes(u) == -1 || 1083 | decode_opcode(u) == -1 || 1084 | u->error; 1085 | /* Handle decode error. */ 1086 | if (u->error) { 1087 | /* clear out the decode data. */ 1088 | clear_insn(u); 1089 | /* mark the sequence of bytes as invalid. */ 1090 | u->itab_entry = &ud_itab[0]; /* entry 0 is invalid */ 1091 | u->mnemonic = u->itab_entry->mnemonic; 1092 | } 1093 | 1094 | /* maybe this stray segment override byte 1095 | * should be spewed out? 1096 | */ 1097 | if ( !P_SEG( u->itab_entry->prefix ) && 1098 | u->operand[0].type != UD_OP_MEM && 1099 | u->operand[1].type != UD_OP_MEM ) 1100 | u->pfx_seg = 0; 1101 | 1102 | u->insn_offset = u->pc; /* set offset of instruction */ 1103 | u->asm_buf_fill = 0; /* set translation buffer index to 0 */ 1104 | u->pc += u->inp_ctr; /* move program counter by bytes decoded */ 1105 | 1106 | /* return number of bytes disassembled. */ 1107 | return u->inp_ctr; 1108 | } 1109 | 1110 | /* 1111 | vim: set ts=2 sw=2 expandtab 1112 | */ 1113 | -------------------------------------------------------------------------------- /src/hook.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | -------------------------------------------------------------------------- 3 | -- Linux hook License 4 | -------------------------------------------------------------------------- 5 | -- 6 | -- Linux hook is licensed under the terms of the MIT license reproduced 7 | -- below. This means that show_affinity is free software and can be used 8 | -- for both academic and commercial purposes at absolutely no cost. 9 | -- 10 | -- ---------------------------------------------------------------------- 11 | -- 12 | -- Copyright (C) 2018-2021 Lei Huang (huang@tacc.utexas.edu) 13 | -- 14 | -- Permission is hereby granted, free of charge, to any person obtaining 15 | -- a copy of this software and associated documentation files (the 16 | -- "Software"), to deal in the Software without restriction, including 17 | -- without limitation the rights to use, copy, modify, merge, publish, 18 | -- distribute, sublicense, and/or sell copies of the Software, and to 19 | -- permit persons to whom the Software is furnished to do so, subject 20 | -- to the following conditions: 21 | -- 22 | -- The above copyright notice and this permission notice shall be 23 | -- included in all copies or substantial portions of the Software. 24 | -- 25 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 27 | -- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | -- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29 | -- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30 | -- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31 | -- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 32 | -- THE SOFTWARE. 33 | -- 34 | -------------------------------------------------------------------------- 35 | *************************************************************************/ 36 | 37 | /* 38 | About: This is a mini framework to hook the functions in shared libraries under Linux. 39 | It only works on x86_64 at this time. I might extend it to support Power PC and ARM 40 | in future. udis86 was adopted to disasseble binary code on x86_64. 41 | 42 | Trampoline is used in hook. 43 | */ 44 | 45 | 46 | #define _GNU_SOURCE 47 | 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | 67 | #include 68 | 69 | #include 70 | #include 71 | #include 72 | #include 73 | #include 74 | #include 75 | 76 | #include "../include/hook.h" 77 | #include "hook_int.h" 78 | 79 | 80 | static int num_hook=0; 81 | static int num_module=0; 82 | static int num_patch_blk=0, is_uninstalled=0; 83 | static int num_called_ModuleMap=0; 84 | 85 | static MODULE_PATCH_INFO module_list[MAX_MODULE]; 86 | 87 | // variables used by udis86 88 | static ud_t ud_obj; 89 | static int ud_idx; 90 | 91 | // The buffer to hold binary code that will be decompiled by udis86. 92 | static char *bin_code_buff=NULL; 93 | 94 | // The flag whethere libc.so is found or not. 95 | static int found_libc=1; 96 | 97 | // The instruction to jump to new function. 98 | //0: ff 25 00 00 00 00 jmp QWORD PTR [rip+0x0] # 6 <_main+0x6> 99 | // The long int +6 (0x1234567812345678) needs be replaced by the address of new function. 100 | static unsigned char instruction_bounce[]={0xff,0x25,0x00,0x00,0x00,0x00, \ 101 | 0x78,0x56,0x34,0x12,0x78,0x56,0x34,0x12}; 102 | 103 | // The list of memory blocks alloated to hold patches for hook 104 | static PATCH_BLOCK patch_blk_list[MAX_MODULE]; 105 | 106 | 107 | //start to compile list of memory blocks in /proc/pid/maps 108 | // The max number of libraries loaded 109 | #define MAX_NUM_LIB (256) 110 | 111 | // The max number of segments in /proc/pid/maps 112 | #define MAX_NUM_SEG (2048) 113 | 114 | static int num_seg=0, num_lib_in_map=0; 115 | 116 | // List of min and max addreses of segments in /proc/pid/maps 117 | static uint64_t addr_min[MAX_NUM_SEG], addr_max[MAX_NUM_SEG]; 118 | 119 | // List of base addresses of loaded libraries 120 | static uint64_t lib_base_addr[MAX_NUM_LIB]; 121 | 122 | // List of names of loaded libraries 123 | static char lib_name_list[MAX_NUM_LIB][MAX_LEN_PATH_NAME]; 124 | //end to compile list of memory blocks in /proc/pid/maps 125 | 126 | static char path_ld[512]=""; 127 | static char path_libc[512]=""; 128 | static char path_libpthread[512]=""; 129 | 130 | 131 | /* 132 | * determine_lib_path - Determine the full paths of three libraries, ld.so, libc.so and libpthread.so. 133 | */ 134 | 135 | static void determine_lib_path(void) 136 | { 137 | int i, pid, size_read; 138 | char read_buff_map[8192], path_file_map[64], *pPos=NULL, *pStart=NULL, *pEnd=NULL, lib_ver_str[32], lib_dir_str[256]; 139 | FILE *fp; 140 | 141 | pid = getpid(); 142 | snprintf(path_file_map, sizeof(path_file_map), "/proc/%d/maps", pid); 143 | fp = fopen(path_file_map, "rb"); 144 | assert(fp != NULL); 145 | 146 | size_read = fread(read_buff_map, 1, sizeof(read_buff_map)-1, fp); 147 | fclose(fp); 148 | 149 | pPos = strstr(read_buff_map, "/ld-2."); 150 | if(pPos == NULL) { 151 | found_libc = 0; 152 | return; 153 | } 154 | for(i=0; i<10; i++) { 155 | if(strncmp(pPos+i, ".so", 3)==0) { 156 | pEnd = pPos+i+3; 157 | break; 158 | } 159 | } 160 | if(pEnd == NULL) { 161 | printf("Fail to determine the ending position of libc path.\nQuit\n"); 162 | exit(1); 163 | } 164 | for(i=0; i<100; i++) { 165 | if(strncmp(pPos-i, " /", 3)==0) { 166 | pStart = pPos-i+2; 167 | break; 168 | } 169 | } 170 | if(pEnd == NULL) { 171 | printf("Fail to determine the starting position of libc path.\nQuit\n"); 172 | exit(1); 173 | } 174 | 175 | memcpy(path_ld, pStart, pEnd-pStart); 176 | path_ld[pEnd-pStart] = 0; 177 | memcpy(lib_ver_str, pPos+4, pEnd-3-(pPos+4)); 178 | lib_ver_str[pEnd-3-(pPos+4)] = 0; 179 | memcpy(lib_dir_str, pStart, pPos-pStart); 180 | lib_dir_str[pPos-pStart] = 0; 181 | 182 | snprintf(path_libc, sizeof(path_libc), "%s/libc-%s.so", lib_dir_str, lib_ver_str); 183 | snprintf(path_libpthread, sizeof(path_libpthread), "%s/libpthread-%s.so", lib_dir_str, lib_ver_str); 184 | 185 | //printf("path_ld = %s\n", path_ld); 186 | //printf("lib_ver_str = %s\n", lib_ver_str); 187 | //printf("lib_dir_str = %s\n", lib_dir_str); 188 | //printf("path_libc = %s\n", path_libc); 189 | //printf("path_libpthread = %s\n", path_libpthread); 190 | } 191 | 192 | /* 193 | * query_func_addr - Determine the addresses and code sizes of functions in func_name_list[]. 194 | * @lib_path: The full path of the shared object file 195 | * @func_name_list: A list of function names in this lib to be intercepted 196 | * @func_addr_list: A list to hold the addreses of functions 197 | * @func_len_list: A list of hold the size (number of bytes) of functions 198 | * @img_base_addr: The base address of this loaded module 199 | * @num_func: The number of functions in the list of func_name_list[] 200 | * Returns: 201 | * void 202 | */ 203 | 204 | static void query_func_addr(const char lib_path[], const char func_name_list[][MAX_LEN_FUNC_NAME], void* func_addr_list[], long int func_len_list[], const long int img_base_addr, const int num_func) 205 | { 206 | int fd, i, j, k; 207 | struct stat file_stat; 208 | void *map_start; 209 | Elf64_Ehdr *header; 210 | Elf64_Shdr *sections; 211 | int strtab_offset=0; 212 | void *symb_base_addr=NULL; 213 | int num_sym=0, sym_rec_size=0, sym_offset, rec_addr; 214 | char *sym_name; 215 | 216 | stat(lib_path, &file_stat); 217 | 218 | fd = open(lib_path, O_RDONLY); 219 | if(fd == -1) { 220 | printf("Fail to open file %s\nQuit\n", lib_path); 221 | exit(1); 222 | } 223 | 224 | map_start = mmap(0, file_stat.st_size, PROT_READ, MAP_SHARED, fd, 0); 225 | if((long int)map_start == -1) { 226 | printf("Fail to mmap file %s\nQuit\n", lib_path); 227 | exit(1); 228 | } 229 | header = (Elf64_Ehdr *) map_start; 230 | 231 | sections = (Elf64_Shdr *)((char *)map_start + header->e_shoff); 232 | 233 | for (i = 0; i < header->e_shnum; i++) { 234 | if ( (sections[i].sh_type == SHT_DYNSYM) || (sections[i].sh_type == SHT_SYMTAB) ) { 235 | symb_base_addr = (void*)(sections[i].sh_offset + map_start); 236 | sym_rec_size = sections[i].sh_entsize; 237 | num_sym = sections[i].sh_size / sections[i].sh_entsize; 238 | 239 | for (j = i-1; j < i+2; j++) { // tricky here!!! 240 | if ( (sections[j].sh_type == SHT_STRTAB) ) { 241 | strtab_offset = (int)(sections[j].sh_offset); 242 | } 243 | } 244 | 245 | // Hash table should be used to be more efficient. 246 | for(j=0; j num_called_ModuleMap = %d\n", num_called_ModuleMap); 381 | 382 | snprintf(szName, sizeof(szName), "/proc/%d/maps", getpid()); 383 | fIn = fopen(szName, "rb"); // non-seekable file. fread is needed!!! 384 | if(fIn == NULL) { 385 | printf("Fail to open file: %s\nQuit\n", szName); 386 | exit(1); 387 | } 388 | 389 | FileSize = fread(szBuf, 1, MAX_MAP_SIZE, fIn); // fread can read complete file. read() does not most of time!!! 390 | fclose(fIn); 391 | 392 | if(FileSize == MAX_MAP_SIZE) { 393 | printf("Warning> FileSize == MAX_MAP_SIZE\nYou might need to increase MAX_MAP_SIZE.\n"); 394 | } 395 | 396 | szBuf[FileSize] = 0; 397 | // printf("%s\n\n", szBuf); 398 | 399 | num_seg = 0; 400 | num_lib_in_map = 0; 401 | szBuf[FileSize] = 0; 402 | 403 | iPos = 0; // start from the beginging 404 | /* 405 | while(iPos >= 0) { 406 | ReadItem = sscanf(szBuf+iPos, "%lx%lx", &addr_B, &addr_E); 407 | if(ReadItem != 2) { 408 | printf("Error in reading addresses.\n"); 409 | } 410 | iPos_Save = iPos; 411 | iPos = get_position_of_next_line(szBuf, iPos + 38, FileSize); // find the next line 412 | if( (iPos - iPos_Save) > 73 ) { // with a lib name 413 | ReadItem = sscanf(szBuf+iPos_Save+73, "%s", szLibName); 414 | if( ReadItem == 1 ) { 415 | if(strstr(szLibName, "/ld-")) { 416 | iPos = iPos_Save; 417 | break; 418 | } 419 | } 420 | } 421 | } 422 | */ 423 | while(iPos >= 0) { 424 | ReadItem = sscanf(szBuf+iPos, "%lx-%lx", &addr_B, &addr_E); 425 | if(ReadItem == 2) { 426 | addr_min[num_seg] = addr_B; 427 | addr_max[num_seg] = addr_E; 428 | if(num_seg >= 1) { 429 | // merge contacted blocks 430 | if(addr_min[num_seg] == addr_max[num_seg-1]) { 431 | addr_max[num_seg-1] = addr_max[num_seg]; 432 | num_seg--; 433 | } 434 | } 435 | num_seg++; 436 | } 437 | iPos_Save = iPos; 438 | iPos = get_position_of_next_line(szBuf, iPos + 38, FileSize); // find the next line 439 | if( (iPos - iPos_Save) > 73 ) { // with a lib name 440 | ReadItem = sscanf(szBuf+iPos_Save+73, "%s", szLibName); 441 | if( ReadItem == 1 ) { 442 | if(strncmp(szLibName, "[stack]", 7)==0) { 443 | num_seg--; 444 | break; 445 | } 446 | if(query_lib_name_in_list(szLibName) == -1) { // a new name not in list 447 | strcpy(lib_name_list[num_lib_in_map], szLibName); 448 | lib_base_addr[num_lib_in_map] = addr_B; 449 | num_lib_in_map++; 450 | if(num_lib_in_map >= MAX_NUM_LIB) { 451 | printf("Warning> lib_base_addr is FULL. You may need to increase MAX_NUM_LIB.\n"); 452 | break; 453 | } 454 | } 455 | } 456 | } 457 | if(num_seg >= MAX_NUM_SEG) { 458 | printf("Warning> num_seg >= MAX_NUM_LIB\nYou may want to increase MAX_NUM_LIB.\n"); 459 | break; 460 | } 461 | } 462 | } 463 | #undef MAX_MAP_SIZE 464 | 465 | /* 466 | * find_usable_block - Try to find an allocated memory block that is close enough to 467 | a give module/shared object. 468 | @idx_mod: The name of shared library. Both short name ("ld") and full name ("ld-2.17.so") are accepted. 469 | * Returns: 470 | * The index of memory block for patches. (-1) means not found usable block. 471 | */ 472 | 473 | static int find_usable_block(int idx_mod) 474 | { 475 | int i; 476 | long int p_Min, p_Max, p_MemBlk; 477 | 478 | p_Min = (long int)(module_list[idx_mod].old_func_addr_min); 479 | p_Max = (long int)(module_list[idx_mod].old_func_addr_max); 480 | 481 | for(i=0; i= 0) { 510 | module_list[idx_mod].idx_patch_blk = IdxBlk; 511 | } 512 | else { // does not exist 513 | pCheck = ( (uint64_t)(module_list[idx_mod].old_func_addr_min) + (uint64_t)(module_list[idx_mod].old_func_addr_max) )/2; 514 | 515 | iSeg = -1; 516 | for(i=0; i= addr_min[i]) && (pCheck <= addr_max[i]) ) { 518 | iSeg = i; 519 | break; 520 | } 521 | } 522 | 523 | if(iSeg < 0) { 524 | printf("Something wrong! The address you queried is not inside any module!\nQuit\n"); 525 | exit(1); 526 | } 527 | p_Alloc = (void*)(addr_max[iSeg]); 528 | 529 | if( iSeg < (num_seg - 1) ) { 530 | if( (addr_min[iSeg+1] - addr_max[iSeg]) < MIN_MEM_SIZE) { 531 | printf("Only %" PRIu64 " bytes available.\nQuit\n", addr_min[iSeg+1] - addr_max[iSeg]); 532 | exit(1); 533 | } 534 | } 535 | 536 | patch_blk_list[num_patch_blk].patch_addr = mmap(p_Alloc, MIN_MEM_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 537 | if(patch_blk_list[num_patch_blk].patch_addr == MAP_FAILED) { 538 | printf("Fail to allocate code block at %p with mmap().\nQuit\n", p_Alloc); 539 | exit(1); 540 | } 541 | else if(patch_blk_list[num_patch_blk].patch_addr != p_Alloc) { 542 | printf("Allocated at %p. Desired at %p\n", patch_blk_list[num_patch_blk].patch_addr, p_Alloc); 543 | } 544 | 545 | patch_blk_list[num_patch_blk].num_trampoline = 0; 546 | patch_blk_list[num_patch_blk].patch_addr_end = patch_blk_list[num_patch_blk].patch_addr + MIN_MEM_SIZE; 547 | num_patch_blk++; 548 | } 549 | } 550 | 551 | return; 552 | } 553 | 554 | /* 555 | * get_position_of_next_line - Determine the offset of the next new line in a string buffer. 556 | * @buff: The string buffer 557 | * @pos_start: The starting offset to search 558 | * @max_buff_size: The max length of buff[] 559 | * Returns: 560 | * The offset of the next new line. (-1) means reaching the end of buffer. 561 | */ 562 | static int get_position_of_next_line(const char buff[], const int pos_start, const int max_buff_size) 563 | { 564 | int i=pos_start; 565 | 566 | while(i < max_buff_size) { 567 | // A new line 568 | if(buff[i] == 0xA) { 569 | i++; 570 | return ( (i>=max_buff_size) ? (-1) : (i) ); 571 | } 572 | else { 573 | i++; 574 | } 575 | } 576 | return (-1); 577 | } 578 | 579 | /* 580 | * determine_mem_block_size - Determine we need to change the permission of one or two pages 581 | * for a given address. 582 | * @addr: The address of the entry of original function. We will change it to a jmp instruction. 583 | * @page_size: The size of one page in current system. 584 | * Returns: 585 | * The number of bytes we need to change permission with mprotect(). 586 | */ 587 | static size_t determine_mem_block_size(const void *addr, const unsigned long int page_size) 588 | { 589 | unsigned long int res, addr_code; 590 | 591 | addr_code = (unsigned long int)addr; 592 | res = addr_code % page_size; 593 | if( (res + 5) > page_size ) { // close to the boundary of two memory pages 594 | return (size_t)(page_size*2); 595 | } 596 | else { 597 | return (size_t)(page_size); 598 | } 599 | } 600 | 601 | // The max number of instruments of the entry code in original function to analyze 602 | #define MAX_INSTUMENTS (24) 603 | 604 | /* 605 | * install_hook - Install hooks by setting up trampolines for all functions registered. 606 | * Returns: 607 | * The number of hooks actually installed. 608 | */ 609 | 610 | int install_hook(void) 611 | { 612 | int j, idx_mod, iFunc, iFunc2, jMax, ReadItem, *p_int, WithJmp[MAX_PATCH]; 613 | int nInstruction, RIP_Offset, Jmp_Offset, nFunc_InBlk, num_hook_installed=0; 614 | int OffsetList[MAX_INSTUMENTS]; 615 | char szHexCode[MAX_INSTUMENTS][64], szInstruction[MAX_INSTUMENTS][128]; 616 | char *pSubStr=NULL, *pOpOrgEntry; 617 | void *pbaseOrg; 618 | size_t MemSize_Modify; 619 | TRAMPOLINE *pTrampoline; 620 | unsigned long int page_size, mask; 621 | 622 | if(found_libc==0) { 623 | return 0; 624 | } 625 | 626 | page_size = sysconf(_SC_PAGESIZE); 627 | mask = ~(page_size - 1); 628 | 629 | query_all_org_func_addr(); 630 | allocate_memory_block_for_patches(); 631 | 632 | for(idx_mod=0; idx_mod= JMP_INSTRCTION_LEN) { // size of jmp instruction 669 | pTrampoline[nFunc_InBlk].saved_code_len = OffsetList[nInstruction]; 670 | if( (nInstruction > 0) && (strncmp(szHexCode[nInstruction-1], "e9", 2)==0) ) { 671 | if(strlen(szHexCode[nInstruction-1]) == 10) { // found a jmp instruction here!!! 672 | if(nInstruction >= 2) { 673 | WithJmp[nFunc_InBlk] = strlen(szHexCode[nInstruction-2])/2 + 1; 674 | } 675 | } 676 | } 677 | break; 678 | } 679 | 680 | strcpy(szHexCode[nInstruction], ud_insn_hex(&ud_obj)); 681 | strcpy(szInstruction[nInstruction], ud_insn_asm(&ud_obj)); 682 | pSubStr = strstr(szInstruction[nInstruction], "[rip+"); 683 | if(pSubStr) { 684 | ReadItem = sscanf(pSubStr+5, "%x]", &RIP_Offset); 685 | if(ReadItem == 1) { 686 | pTrampoline[nFunc_InBlk].offset_rIP_var = RIP_Offset; 687 | } 688 | } 689 | nInstruction++; 690 | if(nInstruction >= MAX_INSTUMENTS) { 691 | printf("WARNING> nInstruction >= MAX_INSTUMENTS\nYou might need to increase MAX_INSTUMENTS.\n"); 692 | break; 693 | } 694 | } 695 | 696 | memcpy(pTrampoline[nFunc_InBlk].bounce, instruction_bounce, BOUNCE_CODE_LEN); 697 | *((unsigned long int *)(pTrampoline[nFunc_InBlk].bounce + OFFSET_NEW_FUNC_ADDR)) = (unsigned long int)(module_list[idx_mod].new_func_addr_list[iFunc]); // the address of new function 698 | 699 | 700 | memcpy(pTrampoline[nFunc_InBlk].trampoline, pTrampoline[nFunc_InBlk].addr_org_func, pTrampoline[nFunc_InBlk].saved_code_len); 701 | pTrampoline[nFunc_InBlk].trampoline[pTrampoline[nFunc_InBlk].saved_code_len] = 0xE9; // jmp 702 | Jmp_Offset = (int) ( ( (long int)(pTrampoline[nFunc_InBlk].addr_org_func) - ( (long int)(pTrampoline[nFunc_InBlk].trampoline) + 5) ) & 0xFFFFFFFF); 703 | *((int*)(pTrampoline[nFunc_InBlk].trampoline + pTrampoline[nFunc_InBlk].saved_code_len + 1)) = Jmp_Offset; 704 | 705 | if(pTrampoline[nFunc_InBlk].offset_rIP_var != NULL_RIP_VAR_OFFSET) { 706 | jMax = pTrampoline[nFunc_InBlk].saved_code_len - 4; 707 | for(j=jMax-2; j<=jMax; j++) { 708 | p_int = (int *)(pTrampoline[nFunc_InBlk].trampoline + j); 709 | if( *p_int == pTrampoline[nFunc_InBlk].offset_rIP_var ) { 710 | *p_int += ( (int)( ( (long int)(pTrampoline[nFunc_InBlk].addr_org_func) - (long int)(pTrampoline[nFunc_InBlk].trampoline) ) ) ); // correct relative offset of PIC var 711 | } 712 | } 713 | } 714 | if(WithJmp[nFunc_InBlk] > 0) { 715 | p_int = (int *)(pTrampoline[nFunc_InBlk].trampoline + WithJmp[nFunc_InBlk]); 716 | *p_int += ( (int)( ( (long int)(pTrampoline[nFunc_InBlk].addr_org_func) - (long int)(pTrampoline[nFunc_InBlk].trampoline) ) ) ); 717 | } 718 | if(pTrampoline[nFunc_InBlk].trampoline[0] == 0xE9) { // First instruction is JMP xxxx. Needs address correction 719 | p_int = (int *)(pTrampoline[nFunc_InBlk].trampoline + 1); // the next four bytes are supposed to be the relative offset 720 | *p_int += ( (int)( ( (long int)(pTrampoline[nFunc_InBlk].addr_org_func) - (long int)(pTrampoline[nFunc_InBlk].trampoline) ) ) ); 721 | } 722 | 723 | // set up function pointers for original functions 724 | *(module_list[idx_mod].ptr_old_func_add_list[iFunc]) = (long int)(pTrampoline[nFunc_InBlk].trampoline); // the entry address to call orginal function 725 | 726 | 727 | pbaseOrg = (void *)( (long int)(pTrampoline[nFunc_InBlk].addr_org_func) & mask ); // fast mod 728 | 729 | MemSize_Modify = determine_mem_block_size((void *)(pTrampoline[nFunc_InBlk].addr_org_func), page_size); 730 | if(mprotect(pbaseOrg, MemSize_Modify, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) { 731 | printf("Error in executing mprotect(). %s\n", module_list[idx_mod].func_name_list[iFunc]); 732 | exit(1); 733 | } 734 | 735 | memcpy(pTrampoline[nFunc_InBlk].org_code, pTrampoline[nFunc_InBlk].addr_org_func, 5); // save orginal code for uninstall 736 | 737 | pOpOrgEntry = (char *)(pTrampoline[nFunc_InBlk].addr_org_func); 738 | pOpOrgEntry[0] = 0xE9; 739 | *((int *)(pOpOrgEntry+1)) = (int)( (long int)(pTrampoline[nFunc_InBlk].bounce) - (long int)(pTrampoline[nFunc_InBlk].addr_org_func) - 5 ); 740 | 741 | if(mprotect(pbaseOrg, MemSize_Modify, PROT_READ | PROT_EXEC) != 0) { 742 | printf("Error in executing mprotect(). %s\n", module_list[idx_mod].func_name_list[iFunc]); 743 | exit(1); 744 | } 745 | 746 | nFunc_InBlk++; 747 | num_hook_installed++; 748 | } 749 | patch_blk_list[module_list[idx_mod].idx_patch_blk].num_trampoline += module_list[idx_mod].num_hook; 750 | } 751 | 752 | return num_hook_installed; 753 | } 754 | #undef MAX_INSTUMENTS 755 | 756 | // Taken from udis86 project 757 | static void init_udis86(void) 758 | { 759 | ud_init(&ud_obj); 760 | ud_set_mode(&ud_obj, 64); // 32 or 64 761 | ud_set_syntax(&ud_obj, UD_SYN_INTEL); // intel syntax 762 | } 763 | 764 | // Taken from udis86 project 765 | static int input_hook_x(ud_t* u) 766 | { 767 | if(ud_idx < MAX_LEN_TO_DISASSEMBLE) { 768 | ud_idx++; 769 | return (int)(bin_code_buff[ud_idx-1] & 0xFF); 770 | } 771 | else { 772 | return UD_EOI; 773 | } 774 | } 775 | 776 | /* 777 | * register_a_hook - Add one target function into the list of the functions to intercept. 778 | * @module_name: The name of shared library. Both short name ("ld") and full name ("ld-2.17.so") are accepted. 779 | * @func_Name: The function name. 780 | * @new_func_addr: The address of our new implementation. 781 | * @ptr_org_func: *ptr_org_func will hold the address of orginal function implemented in lib module_name. 782 | * Returns: 783 | * 0: success; otherwise fail. 784 | */ 785 | int register_a_hook(const char *module_name, const char *func_name, const void *new_func_addr, const long int *ptr_org_func) 786 | { 787 | void *module; 788 | int idx, idx_mod; 789 | char module_name_local[MAX_LEN_PATH_NAME]; 790 | 791 | // make sure module_name[] and func_name[] are not too long. 792 | if(strlen(module_name) >= MAX_LEN_PATH_NAME) { 793 | return REGISTER_MODULE_NAME_TOO_LONG; 794 | } 795 | if(strlen(func_name) >= MAX_LEN_FUNC_NAME) { 796 | return REGISTER_FUNC_NAME_TOO_LONG; 797 | } 798 | 799 | // Do some initialization work at the first time. 800 | if( !num_hook ) { 801 | memset(module_list, 0, sizeof(MODULE_PATCH_INFO)*MAX_MODULE); 802 | memset(patch_blk_list, 0, sizeof(PATCH_BLOCK)*MAX_MODULE); 803 | 804 | init_udis86(); 805 | determine_lib_path(); 806 | } 807 | 808 | if(found_libc==0) { 809 | return REGISTER_NOT_FOUND_LIBC; 810 | } 811 | 812 | if(num_called_ModuleMap == 0) { 813 | get_module_maps(); 814 | num_called_ModuleMap++; 815 | } 816 | 817 | if( strcmp(module_name, "ld") == 0 ) { 818 | strcpy(module_name_local, path_ld); 819 | } 820 | else if( strcmp(module_name, "libc") == 0 ) { 821 | strcpy(module_name_local, path_libc); 822 | } 823 | else if( strcmp(module_name, "libpthread") == 0 ) { 824 | strcpy(module_name_local, path_libpthread); 825 | } 826 | else { 827 | strcpy(module_name_local, module_name); 828 | } 829 | 830 | if(module_name_local[0] == '/') { // absolute path 831 | if( query_lib_name_in_list(module_name_local) == -1 ) { // not loaded yet 832 | module = dlopen(module_name_local, RTLD_LAZY); // load the library 833 | if(module == NULL) { 834 | printf("Error> Fail to dlopen: %s.\n", module_name_local); 835 | return REGISTER_DLOPEN_FAILED; 836 | } 837 | get_module_maps(); 838 | } 839 | } 840 | 841 | idx = query_lib_name_in_list(module_name_local); 842 | if( idx == -1 ) { 843 | printf("Failed to find %s in /proc/pid/maps\nQuit\n", module_name_local); 844 | exit(1); 845 | } 846 | 847 | idx_mod = query_registered_module(module_name_local); 848 | if(idx_mod == -1) { // not registered module name. Register it. 849 | strcpy(module_list[num_module].module_name, module_name_local); 850 | module_list[num_module].module_base_addr = lib_base_addr[idx]; 851 | strcpy(module_list[num_module].func_name_list[module_list[num_module].num_hook], func_name); 852 | module_list[num_module].new_func_addr_list[module_list[num_module].num_hook] = (void*)new_func_addr; 853 | module_list[num_module].ptr_old_func_add_list[module_list[num_module].num_hook] = (long int *)ptr_org_func; 854 | module_list[num_module].num_hook = 1; 855 | num_module++; 856 | } 857 | else { 858 | if(module_list[idx_mod].module_base_addr != lib_base_addr[idx]) { 859 | printf("WARING> module_list[idx_mod].module_base_addr != lib_base_addr[idx]\n"); 860 | } 861 | 862 | strcpy(module_list[idx_mod].func_name_list[module_list[idx_mod].num_hook], func_name); 863 | module_list[idx_mod].new_func_addr_list[module_list[idx_mod].num_hook] = (void *)new_func_addr; 864 | module_list[idx_mod].ptr_old_func_add_list[module_list[idx_mod].num_hook] = (long int *)ptr_org_func; 865 | module_list[idx_mod].num_hook ++; 866 | } 867 | 868 | num_hook++; 869 | 870 | if(num_hook > MAX_PATCH) { 871 | printf("Error> num_hook > MAX_PATCH\nQuit\n"); 872 | return REGISTER_TOO_MANY_HOOKS; 873 | } 874 | 875 | return REGISTER_SUCCESS; 876 | } 877 | 878 | /* 879 | * query_all_org_func_addr - Queries the addresses of all orginal functions to hook. 880 | * Returns: 881 | * void 882 | */ 883 | static void query_all_org_func_addr(void) 884 | { 885 | int idx, idx_mod, iFunc; 886 | 887 | get_module_maps(); // update module map 888 | 889 | for(idx_mod=0; idx_mod module_list[idx_mod].old_func_addr_list[iFunc]) { 923 | module_list[idx_mod].old_func_addr_min = module_list[idx_mod].old_func_addr_list[iFunc]; 924 | } 925 | if(module_list[idx_mod].old_func_addr_max < module_list[idx_mod].old_func_addr_list[iFunc]) { 926 | module_list[idx_mod].old_func_addr_max = module_list[idx_mod].old_func_addr_list[iFunc]; 927 | } 928 | } 929 | //printf("module_list[%d], %d functions, %s, 0x%p, 0x%p\n", idx_mod, module_list[idx_mod].num_hook, module_list[idx_mod].module_name, module_list[idx_mod].OrgFuncMin, module_list[idx_mod].OrgFuncMax); 930 | } 931 | } 932 | --------------------------------------------------------------------------------