From fb67c963ce21fff0c629ee76bb843717ad11f77a Mon Sep 17 00:00:00 2001 From: renoseven Date: Sat, 15 Feb 2025 17:05:06 +0800 Subject: [PATCH] upatch-diff: format code Signed-off-by: renoseven --- upatch-diff/create-diff-object.c | 367 ++--- upatch-diff/elf-common.c | 145 +- upatch-diff/elf-common.h | 191 +-- upatch-diff/elf-compare.c | 556 ++++---- upatch-diff/elf-compare.h | 2 +- upatch-diff/elf-correlate.c | 515 +++---- upatch-diff/elf-correlate.h | 2 +- upatch-diff/elf-create.c | 210 ++- upatch-diff/elf-create.h | 2 +- upatch-diff/elf-debug.c | 80 +- upatch-diff/elf-insn.c | 118 +- upatch-diff/elf-resolve.c | 5 +- upatch-diff/elf-resolve.h | 2 +- upatch-diff/insn/asm/inat-tables.h | 2024 ++++++++++++++-------------- upatch-diff/insn/asm/inat.h | 162 ++- upatch-diff/insn/asm/insn.h | 183 +-- upatch-diff/insn/inat.c | 99 +- upatch-diff/insn/insn.c | 861 ++++++------ upatch-diff/list.h | 115 +- upatch-diff/log.h | 50 +- upatch-diff/running-elf.c | 42 +- upatch-diff/running-elf.h | 6 +- upatch-diff/upatch-dynrela.h | 2 +- upatch-diff/upatch-elf.c | 170 ++- upatch-diff/upatch-elf.h | 140 +- upatch-diff/upatch-patch.h | 4 +- 26 files changed, 3201 insertions(+), 2852 deletions(-) diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c index 0eea3624..02d43c21 100644 --- a/upatch-diff/create-diff-object.c +++ b/upatch-diff/create-diff-object.c @@ -62,7 +62,7 @@ #define PROG_VERSION "upatch-diff "BUILD_VERSION -enum LogLevel g_loglevel = NORMAL; +enum log_level g_loglevel = NORMAL; char *g_logprefix; char *g_uelf_name; char *g_relf_name; @@ -87,7 +87,8 @@ static struct argp_option options[] = { static char program_doc[] = "upatch-build -- generate a patch object based on the source object"; -static char args_doc[] = "-s source_obj -p patched_obj -r elf_file -o output_obj"; +static char args_doc[] = + "-s source_obj -p patched_obj -r elf_file -o output_obj"; const char *argp_program_version = PROG_VERSION; @@ -99,8 +100,8 @@ static error_t check_opt(struct argp_state *state) arguments->patched_obj == NULL || arguments->running_elf == NULL || arguments->output_obj == NULL) { - argp_usage(state); - return ARGP_ERR_UNKNOWN; + argp_usage(state); + return ARGP_ERR_UNKNOWN; } return 0; } @@ -109,8 +110,7 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { struct arguments *arguments = state->input; - switch (key) - { + switch (key) { case 'd': arguments->debug = true; break; @@ -136,7 +136,9 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) return 0; } -static struct argp argp = {options, parse_opt, args_doc, program_doc, NULL, NULL, NULL}; +static struct argp argp = { + options, parse_opt, args_doc, program_doc, NULL, NULL, NULL +}; /* * Key point for chreate-diff-object: @@ -155,16 +157,17 @@ static void show_program_info(struct arguments *arguments) log_debug("output object: %s\n", arguments->output_obj); } -static void compare_elf_headers(struct upatch_elf *uelf_source, struct upatch_elf *uelf_patched) +static void compare_elf_headers(struct upatch_elf *uelf_source, + struct upatch_elf *uelf_patched) { GElf_Ehdr ehdr_source, ehdr_patched; - if (!gelf_getehdr(uelf_source->elf, &ehdr_source)) + if (!gelf_getehdr(uelf_source->elf, &ehdr_source)) { ERROR("gelf_getehdr source failed for %s.", elf_errmsg(0)); - - if (!gelf_getehdr(uelf_patched->elf, &ehdr_patched)) + } + if (!gelf_getehdr(uelf_patched->elf, &ehdr_patched)) { ERROR("gelf_getehdr patched failed for %s.", elf_errmsg(0)); - + } if (memcmp(ehdr_source.e_ident, ehdr_patched.e_ident, EI_NIDENT) || ehdr_source.e_type != ehdr_patched.e_type || ehdr_source.e_machine != ehdr_patched.e_machine || @@ -175,32 +178,35 @@ static void compare_elf_headers(struct upatch_elf *uelf_source, struct upatch_el ehdr_source.e_ehsize != ehdr_patched.e_ehsize || ehdr_source.e_phentsize != ehdr_patched.e_phentsize || ehdr_source.e_shentsize != ehdr_patched.e_shentsize) { - ERROR("compare_elf_headers failed."); - } + ERROR("compare_elf_headers failed."); + } } /* we can sure we only handle relocatable file, this is unnecessary */ static void check_program_headers(struct upatch_elf *uelf) { size_t ph_nr; - if (elf_getphdrnum(uelf->elf, &ph_nr)) - ERROR("elf_getphdrnum with error %s.", elf_errmsg(0)); - if (ph_nr != 0) + if (elf_getphdrnum(uelf->elf, &ph_nr)) { + ERROR("elf_getphdrnum with error %s.", elf_errmsg(0)); + } + if (ph_nr != 0) { ERROR("ELF contains program header."); + } } static char *strarrcmp(char *name, char **prefix) { size_t len; - if (name == NULL) + if (name == NULL) { return NULL; - + } while (*prefix != NULL) { len = strlen(*prefix); - if (!strncmp(name, *prefix, len)) + if (!strncmp(name, *prefix, len)) { return name + len; + } prefix++; } @@ -229,27 +235,33 @@ static bool is_bundleable(struct symbol *sym) NULL, }; - if (sym == NULL || sym->sec == NULL) + if (sym == NULL || sym->sec == NULL) { return false; + } - if (sym->type == STT_FUNC) + if (sym->type == STT_FUNC) { name = strarrcmp(sym->sec->name, func_prefix); - else if (sym->type == STT_OBJECT) + } else if (sym->type == STT_OBJECT) { name = strarrcmp(sym->sec->name, obj_prefix); + } /* no prefix found or invalid type */ - if (name == NULL) + if (name == NULL) { return false; - - if (!strcmp(name, sym->name)) + } + if (!strcmp(name, sym->name)) { return true; + } /* special case for cold func */ text_name_len = strlen(".text.unlikely."); - if (sym->type == STT_FUNC && !strncmp(sym->sec->name, ".text.unlikely.", text_name_len) && + if (sym->type == STT_FUNC && + !strncmp(sym->sec->name, ".text.unlikely.", text_name_len) && strstr(sym->name, ".cold") && - !strncmp(sym->sec->name + text_name_len, sym->name, strlen(sym->sec->name) - text_name_len)) + !strncmp(sym->sec->name + text_name_len, sym->name, + strlen(sym->sec->name) - text_name_len)) { return true; + } return false; } @@ -267,7 +279,7 @@ static void bundle_symbols(struct upatch_elf *uelf) if (is_bundleable(sym)) { if (sym->sym.st_value != 0 && is_gcc6_localentry_bundled_sym(uelf)) { - ERROR("Symbol '%s' at offset %lu within section '%s', expected 0.", + ERROR("Symbol '%s' at offset %lu of section '%s', expected 0.", sym->name, sym->sym.st_value, sym->sec->name); } sym->sec->sym = sym; @@ -291,24 +303,27 @@ static void detect_child_functions(struct upatch_elf *uelf) char *pname; list_for_each_entry(sym, &uelf->symbols, list) { - if (sym->type != STT_FUNC) + if (sym->type != STT_FUNC) { continue; - + } childstr = strstr(sym->name, ".cold"); - if (!childstr) + if (!childstr) { childstr = strstr(sym->name, ".part"); - - if (!childstr) + } + if (!childstr) { continue; + } pname = strndup(sym->name, (size_t)(childstr - sym->name)); log_debug("symbol '%s', pname: '%s'\n", sym->name, pname); - if (!pname) + if (!pname) { ERROR("detect_child_functions strndup failed."); + } sym->parent = find_symbol_by_name(&uelf->symbols, pname); - if (sym->parent) + if (sym->parent) { list_add_tail(&sym->subfunction_node, &sym->parent->children); + } free(pname); } @@ -316,32 +331,35 @@ static void detect_child_functions(struct upatch_elf *uelf) static bool discarded_sym(struct running_elf *relf, struct symbol *sym) { - if (!sym || !sym->sec || !sym->sec->name) - return false; - + if (!sym || !sym->sec || !sym->sec->name) { + return false; + } /* - * ".gnu.warning." section is to prevent some symbols in the dynamic library being used by external programs. - * in the exec program, these sections are discarded in linker. so we discard these symbols. + * ".gnu.warning." section is to prevent some symbols + * in the dynamic library being used by external programs. + * In the exec program, these sections are discarded in linker. + * so we discard these symbols. */ - if (relf->is_exec && !strncmp(sym->sec->name, ".gnu.warning.", strlen(".gnu.warning."))) - return true; + if (relf->is_exec && + !strncmp(sym->sec->name, ".gnu.warning.", strlen(".gnu.warning."))) { + return true; + } - return false; + return false; } -enum LOCAL_MATCH { +enum local_match { FOUND, NOT_FOUND, EMPTY, }; -static enum LOCAL_MATCH locals_match( - struct upatch_elf *uelf, struct running_elf *relf, - struct symbol *file_sym, int file_sym_idx) +static enum local_match locals_match(struct upatch_elf *uelf, + struct running_elf *relf, struct symbol *file_sym, int file_sym_idx) { struct symbol *uelf_sym = NULL; struct debug_symbol *relf_sym = NULL; - enum LOCAL_MATCH found = EMPTY; + enum local_match found = EMPTY; for (int i = file_sym_idx + 1; i < relf->obj_nr; i++) { relf_sym = &relf->obj_syms[i]; @@ -363,7 +381,7 @@ static enum LOCAL_MATCH locals_match( if (uelf_sym->type == STT_FILE) { break; // find until next file } - if(uelf_sym->bind != STB_LOCAL) { + if (uelf_sym->bind != STB_LOCAL) { continue; } if ((uelf_sym->type == relf_sym->type) && @@ -385,7 +403,7 @@ static enum LOCAL_MATCH locals_match( if (uelf_sym->type == STT_FILE) { break; // find until next file } - if(uelf_sym->bind != STB_LOCAL) { + if (uelf_sym->bind != STB_LOCAL) { continue; } if ((relf_sym->type != STT_FUNC) && @@ -428,7 +446,7 @@ static void find_local_syms(struct upatch_elf *uelf, struct running_elf *relf, { struct debug_symbol *relf_sym = NULL; struct debug_symbol *found_sym = NULL; - enum LOCAL_MATCH found; + enum local_match found; for (int i = 0; i < relf->obj_nr; i++) { relf_sym = &relf->obj_syms[i]; @@ -443,12 +461,10 @@ static void find_local_syms(struct upatch_elf *uelf, struct running_elf *relf, found = locals_match(uelf, relf, file_sym, i); if (found == NOT_FOUND) { continue; - } - else if (found == EMPTY) { + } else if (found == EMPTY) { found_sym = relf_sym; break; - } - else { + } else { if (found_sym) { ERROR("Found duplicate local symbols in '%s'", g_relf_name); } @@ -469,8 +485,8 @@ static void find_local_syms(struct upatch_elf *uelf, struct running_elf *relf, } /* - * Because there can be duplicate symbols in elf, we need correlate each symbol from - * source elf to it's corresponding symbol in running elf. + * Because there can be duplicate symbols in elf, we need correlate each symbol + * from source elf to it's corresponding symbol in running elf. * Both the source elf and the running elf can be split on STT_FILE * symbols into blocks of symbols originating from a single source file. * We then compare local symbol lists from both blocks and store the pointer @@ -509,24 +525,28 @@ static void mark_file_symbols(struct upatch_elf *uelf) static void mark_grouped_sections(struct upatch_elf *uelf) { - struct section *groupsec, *sec; - unsigned int *data, *end; + struct section *groupsec; + struct section *sec; + unsigned int *data; + unsigned int *end; list_for_each_entry(groupsec, &uelf->sections, list) { - if (groupsec->sh.sh_type != SHT_GROUP) + if (groupsec->sh.sh_type != SHT_GROUP) { continue; - data = groupsec->data->d_buf; - end = groupsec->data->d_buf + groupsec->data->d_size; - data++; /* skip first flag word (e.g. GRP_COMDAT) */ - while (data < end) { - sec = find_section_by_index(&uelf->sections, *data); - if (!sec) - ERROR("Group section not found"); - sec->grouped = 1; - log_debug("Marking section '%s' (%d) as grouped\n", - sec->name, sec->index); - data++; - } + } + data = groupsec->data->d_buf; + end = groupsec->data->d_buf + groupsec->data->d_size; + data++; /* skip first flag word (e.g. GRP_COMDAT) */ + while (data < end) { + sec = find_section_by_index(&uelf->sections, *data); + if (!sec) { + ERROR("Group section not found"); + } + sec->grouped = 1; + log_debug("Marking section '%s' (%d) as grouped\n", + sec->name, sec->index); + data++; + } } } @@ -545,26 +565,32 @@ static void replace_section_syms(struct upatch_elf *uelf) bool found = false; list_for_each_entry(relasec, &uelf->sections, list) { - if (!is_rela_section(relasec) || is_debug_section(relasec) || is_note_section(relasec)) + if (!is_rela_section(relasec) || + is_debug_section(relasec) || + is_note_section(relasec)) { continue; + } list_for_each_entry(rela, &relasec->relas, list) { - if (!rela->sym || !rela->sym->sec || rela->sym->type != STT_SECTION) + if (!rela->sym || !rela->sym->sec || + rela->sym->type != STT_SECTION) { continue; - - log_debug("Found replace symbol for section '%s' \n", rela->sym->name); + } + log_debug("Found replace symbol for section '%s'\n", + rela->sym->name); /* * for section symbol, rela->sym->sec is the section itself. - * rela->sym->sec->sym is the bundleable symbol which is a function or object. + * rela->sym->sec->sym is the bundleable symbol which is + * a function or object. */ if (rela->sym->sec->sym) { - log_debug("Act: Replace it with '%s' <- '%s' \n", rela->sym->sec->sym->name, rela->sym->sec->name); + log_debug("Act: Replace it with '%s' <- '%s'\n", + rela->sym->sec->sym->name, rela->sym->sec->name); rela->sym = rela->sym->sec->sym; - - if (rela->sym->sym.st_value != 0) + if (rela->sym->sym.st_value != 0) { ERROR("Symbol offset is not zero."); - + } continue; } @@ -572,9 +598,13 @@ static void replace_section_syms(struct upatch_elf *uelf) list_for_each_entry(sym, &uelf->symbols, list) { long start, end; - /* find object which belongs to this section, it could be .data .rodata etc */ - if (sym->type == STT_SECTION || sym->sec != rela->sym->sec) + /* + * find object which belongs to this section, + * it could be .data .rodata etc. + */ + if (sym->type == STT_SECTION || sym->sec != rela->sym->sec) { continue; + } start = (long)sym->sym.st_value; end = (long)(sym->sym.st_value + sym->sym.st_size); @@ -582,17 +612,20 @@ static void replace_section_syms(struct upatch_elf *uelf) /* text section refer other sections */ if (is_text_section(relasec->base) && !is_text_section(sym->sec) && - (rela->type == R_X86_64_32S || rela->type == R_X86_64_32 || rela->type == R_AARCH64_ABS64) && + (rela->type == R_X86_64_32S || + rela->type == R_X86_64_32 || + rela->type == R_AARCH64_ABS64) && rela->addend == (long)sym->sec->sh.sh_size && - end == (long)sym->sec->sh.sh_size) + end == (long)sym->sec->sh.sh_size) { ERROR("Relocation refer end of data sections."); - else if (target_off == start && target_off == end){ - if(is_mapping_symbol(uelf, sym)) + } else if (target_off == start && target_off == end) { + if (is_mapping_symbol(uelf, sym)) { continue; + } log_debug("Find relocation reference for empty symbol.\n"); - } - else if (target_off < start || target_off >= end) + } else if (target_off < start || target_off >= end) { continue; + } log_debug("'%s': Replacing '%s+%ld' reference with '%s+%ld'\n", relasec->name, rela->sym->name, rela->addend, @@ -653,9 +686,9 @@ static void mark_ignored_sections(struct upatch_elf *uelf) list_for_each_entry(sec, &uelf->sections, list) { if (!strncmp(sec->name, ".discard", strlen(".discard")) || !strncmp(sec->name, ".rela.discard", strlen(".rela.discard"))) { - log_debug("Found discard section '%s'\n", sec->name); - sec->ignore = 1; - } + log_debug("Found discard section '%s'\n", sec->name); + sec->ignore = 1; + } } /* TODO: handle ignore information from sections or settings */ @@ -672,26 +705,30 @@ static void mark_ignored_sections_same(void) {} * We use st_other to mark these symbols. */ static void include_special_local_section(struct upatch_elf *uelf) { - struct symbol *sym, *sym_changed; + struct symbol *sym; + struct symbol *sym_changed; struct rela *rela; list_for_each_entry(sym_changed, &uelf->symbols, list) { - if (!(sym_changed->status == CHANGED && sym_changed->type == STT_FUNC)) + if (!(sym_changed->status == CHANGED && sym_changed->type == STT_FUNC)) { continue; - - if (!sym_changed->sec || !sym_changed->sec->rela) + } + if (!sym_changed->sec || !sym_changed->sec->rela) { continue; + } list_for_each_entry(rela, &sym_changed->sec->rela->relas, list) { sym = rela->sym; - if (sym->sec && sym->status == SAME && sym->bind == STB_LOCAL && !sym->sec->include) { + if (sym->sec && sym->bind == STB_LOCAL && + sym->status == SAME && !sym->sec->include) { sym->sym.st_other |= SYM_OTHER; sym->sec->include = 1; sym->sec->data->d_buf = NULL; sym->sec->data->d_size = 0; // arm error: (.debug_info+0x...) undefined reference to `no symbol' - if (sym->sec->secsym) + if (sym->sec->secsym) { sym->sec->secsym->include = 1; + } } } } @@ -700,16 +737,15 @@ static void include_special_local_section(struct upatch_elf *uelf) { static void include_section(struct section *sec); static void include_symbol(struct symbol *sym) { - if (sym->include) + if (sym->include) { return; - + } /* * The symbol gets included even if its section isn't needed, as it * might be needed: either permanently for a rela, or temporarily for * the later creation of a dynrela. */ sym->include = 1; - /* * For a function/object symbol, if it has a section, we only need to * include the section if it has changed. Otherwise the symbol will be @@ -718,27 +754,32 @@ static void include_symbol(struct symbol *sym) * For section symbols, we always include the section because * references to them can't otherwise be resolved externally. */ - if (sym->sec && (sym->type == STT_SECTION || sym->status != SAME)) + if (sym->sec && (sym->type == STT_SECTION || sym->status != SAME)) { include_section(sym->sec); + } } static void include_section(struct section *sec) { struct rela *rela; - if (sec->include) + if (sec->include) { return; + } sec->include = 1; - if (sec->secsym) + if (sec->secsym) { sec->secsym->include = 1; + } - if (!sec->rela) + if (!sec->rela) { return; + } sec->rela->include = 1; - list_for_each_entry(rela, &sec->rela->relas, list) + list_for_each_entry(rela, &sec->rela->relas, list) { include_symbol(rela->sym); + } } static void include_standard_elements(struct upatch_elf *uelf) @@ -751,14 +792,16 @@ static void include_standard_elements(struct upatch_elf *uelf) !strcmp(sec->name, ".strtab") || !strcmp(sec->name, ".symtab") || !strcmp(sec->name, ".rodata") || - is_string_literal_section(sec)) + is_string_literal_section(sec)) { include_section(sec); + } } - list_for_each_entry(sym, &uelf->symbols, list) - if (sym->sec && is_string_literal_section(sym->sec)) + list_for_each_entry(sym, &uelf->symbols, list) { + if (sym->sec && is_string_literal_section(sym->sec)) { sym->include = 1; - + } + } /* include the NULL symbol */ list_entry(uelf->symbols.next, struct symbol, list)->include = 1; } @@ -774,7 +817,6 @@ static int include_changed_functions(struct upatch_elf *uelf) changed_nr++; include_symbol(sym); } - /* exception handler is a special function */ if (sym->status == CHANGED && sym->type == STT_SECTION && @@ -783,9 +825,9 @@ static int include_changed_functions(struct upatch_elf *uelf) changed_nr++; include_symbol(sym); } - - if (sym->type == STT_FILE) + if (sym->type == STT_FILE) { sym->include = 1; + } } return changed_nr; @@ -797,8 +839,7 @@ static int include_new_globals(struct upatch_elf *uelf) int nr = 0; list_for_each_entry(sym, &uelf->symbols, list) { - if (sym->bind == STB_GLOBAL && sym->sec && - sym->status == NEW) { + if (sym->bind == STB_GLOBAL && sym->sec && sym->status == NEW) { include_symbol(sym); nr++; } @@ -809,19 +850,21 @@ static int include_new_globals(struct upatch_elf *uelf) static void include_debug_sections(struct upatch_elf *uelf) { - struct rela *rela, *saferela; - struct section *sec = NULL, *eh_sec = NULL; + struct rela *rela; + struct rela *saferela; + struct section *sec = NULL; + struct section *eh_sec = NULL; /* include all .debug_* sections */ list_for_each_entry(sec, &uelf->sections, list) { if (is_debug_section(sec)) { sec->include = 1; - - if (!is_rela_section(sec) && sec->secsym) + if (!is_rela_section(sec) && sec->secsym) { sec->secsym->include = 1; - - if (!is_rela_section(sec) && is_eh_frame(sec)) + } + if (!is_rela_section(sec) && is_eh_frame(sec)) { eh_sec = sec; + } } } @@ -831,19 +874,20 @@ static void include_debug_sections(struct upatch_elf *uelf) * for eh_frame section, sync the FDE at the same time */ list_for_each_entry(sec, &uelf->sections, list) { - if (!is_rela_section(sec) || !is_debug_section(sec)) + if (!is_rela_section(sec) || !is_debug_section(sec)) { continue; - - list_for_each_entry_safe(rela, saferela, &sec->relas, list) + } + list_for_each_entry_safe(rela, saferela, &sec->relas, list) { // The shndex of symbol is SHN_COMMON, there is no related section if (rela->sym && !rela->sym->include) { list_del(&rela->list); free(rela); } + } } - - if (eh_sec) + if (eh_sec) { upatch_rebuild_eh_frame(eh_sec); + } } /* currently, there si no special section need to be handled */ @@ -855,7 +899,7 @@ static bool has_tls_included(struct upatch_elf *uelf) list_for_each_entry(sym, &uelf->symbols, list) { if (sym->include == 1 && sym->type == STT_TLS) { - log_normal("TLS symbol '%s' included, but it's not supported", sym->name); + log_normal("TLS symbol '%s' is not supported", sym->name); return true; } } @@ -869,40 +913,47 @@ static void verify_patchability(struct upatch_elf *uelf) list_for_each_entry(sec, &uelf->sections, list) { if (sec->status == CHANGED && !sec->include && !is_rela_section(sec)) { - log_normal("Section '%s' is changed, but it is not selected for inclusion\n", sec->name); + log_normal("Section '%s' changed, but not included\n", sec->name); errs++; } if (sec->status != SAME && sec->grouped) { - log_normal("Section '%s' is changed, but it is a part of a section group\n", sec->name); + log_normal("Section '%s' is changed, but it is in section group\n", + sec->name); errs++; } if (sec->sh.sh_type == SHT_GROUP && sec->status == NEW) { - log_normal("Section '%s' is new, but type 'SHT_GROUP' is not supported\n", sec->name); + log_normal("Section '%s' is new, but it is not supported\n", + sec->name); errs++; } - if (sec->include && sec->status != NEW && - (!strncmp(sec->name, ".data", 5) || !strncmp(sec->name, ".bss", 4)) && - (strcmp(sec->name, ".data.unlikely") && strcmp(sec->name, ".data.once"))) { - log_normal("Data section '%s' is selected for inclusion\n", sec->name); + if ((sec->include && sec->status != NEW) && + (!strncmp(sec->name, ".data", 5) || + !strncmp(sec->name, ".bss", 4)) && + (strcmp(sec->name, ".data.unlikely") && + strcmp(sec->name, ".data.once"))) { + log_normal("Data section '%s' is included", sec->name); errs++; } } - if (errs) - DIFF_FATAL("%d, Unsupported section changes", errs); - + if (errs) { + ERROR("%d, Unsupported section changes", errs); + } if (has_tls_included(uelf)) { - DIFF_FATAL("Unsupported symbol included"); + ERROR("Unsupported symbol included"); } } -static void migrate_included_elements(struct upatch_elf *uelf_patched, struct upatch_elf *uelf_out) +static void migrate_included_elements(struct upatch_elf *uelf_patched, + struct upatch_elf *uelf_out) { - struct section *sec, *safesec; - struct symbol *sym, *safesym; + struct section *sec; + struct section *safesec; + struct symbol *sym; + struct symbol *safesym; memset(uelf_out, 0, sizeof(struct upatch_elf)); uelf_out->arch = uelf_patched->arch; @@ -913,48 +964,58 @@ static void migrate_included_elements(struct upatch_elf *uelf_patched, struct up /* migrate included sections from uelf_patched to uelf_out */ list_for_each_entry_safe(sec, safesec, &uelf_patched->sections, list) { - if (!sec->include) + if (!sec->include) { continue; - + } list_del(&sec->list); list_add_tail(&sec->list, &uelf_out->sections); sec->index = 0; - if (!is_rela_section(sec) && sec->secsym && !sec->secsym->include) + + if (!is_rela_section(sec) && sec->secsym && !sec->secsym->include) { sec->secsym = NULL; // break link to non-included section symbol + } } /* migrate included symbols from kelf to out */ list_for_each_entry_safe(sym, safesym, &uelf_patched->symbols, list) { - if (!sym->include) + if (!sym->include) { continue; + } list_del(&sym->list); list_add_tail(&sym->list, &uelf_out->symbols); sym->index = 0; sym->strip = SYMBOL_DEFAULT; - if (sym->sec && !sym->sec->include) + + if (sym->sec && !sym->sec->include) { sym->sec = NULL; // break link to non-included section + } } } int main(int argc, char*argv[]) { struct arguments arguments; - struct upatch_elf uelf_source, uelf_patched, uelf_out; + struct upatch_elf uelf_source; + struct upatch_elf uelf_patched; + struct upatch_elf uelf_out; struct running_elf relf; - int num_changed, new_globals_exist; + int num_changed; + int new_globals_exist; memset(&arguments, 0, sizeof(arguments)); argp_parse(&argp, argc, argv, 0, NULL, &arguments); - if (arguments.debug) + if (arguments.debug) { g_loglevel = DEBUG; + } g_logprefix = basename(arguments.source_obj); show_program_info(&arguments); - if (elf_version(EV_CURRENT) == EV_NONE) + if (elf_version(EV_CURRENT) == EV_NONE) { ERROR("ELF library initialization failed"); + } /* TODO: with debug info, this may changed */ g_uelf_name = arguments.source_obj; @@ -1008,7 +1069,6 @@ int main(int argc, char*argv[]) upatch_elf_close(&uelf_patched); relf_close(&relf); - return 0; } @@ -1062,7 +1122,8 @@ int main(int argc, char*argv[]) upatch_dump_kelf(&uelf_out); - upatch_write_output_elf(&uelf_out, uelf_patched.elf, arguments.output_obj, 0664); + upatch_write_output_elf(&uelf_out, uelf_patched.elf, arguments.output_obj, + 0664); upatch_elf_destroy(&uelf_source); upatch_elf_destroy(&uelf_patched); diff --git a/upatch-diff/elf-common.c b/upatch-diff/elf-common.c index a74da3aa..5aa35f19 100644 --- a/upatch-diff/elf-common.c +++ b/upatch-diff/elf-common.c @@ -31,95 +31,104 @@ int mangled_strcmp(char *str1, char *str2) /* * ELF string sections aren't mangled, though they look that way. */ - if (strstr(str1, ".str1.")) - return strcmp(str1, str2); - - while (*str1 == *str2) { - if (!*str2) - return 0; + if (strstr(str1, ".str1.")) { + return strcmp(str1, str2); + } + while (*str1 == *str2) { + if (!*str2) { + return 0; + } // format like ".[0-9]" - if (*str1 == '.' && isdigit(str1[1])) { - if (!isdigit(str2[1])) - return 1; - while (isdigit(*++str1)) - ; - while (isdigit(*++str2)) - ; - } else { - str1++; - str2++; - } - } - - if ((!*str1 && has_digit_tail(str2)) || - (!*str2 && has_digit_tail(str1))) - return 0; - - return 1; + if (*str1 == '.' && isdigit(str1[1])) { + if (!isdigit(str2[1])) { + return 1; + } + while (isdigit(*++str1)) { + // empty loop body + } + while (isdigit(*++str2)) { + // empty loop body + } + } else { + str1++; + str2++; + } + } + + if ((!*str1 && has_digit_tail(str2)) || + (!*str2 && has_digit_tail(str1))) { + return 0; + } + + return 1; } bool is_normal_static_local(struct symbol *sym) { // only handle local variable - if (sym->type != STT_OBJECT || sym->bind != STB_LOCAL) - return false; - + if (sym->type != STT_OBJECT || sym->bind != STB_LOCAL) { + return false; + } // TODO: .Local ? need a example here - if (!strncmp(sym->name, ".L", 2)) { - ERROR("find no-local variable \n"); - return false; + if (!strncmp(sym->name, ".L", 2)) { + ERROR("find no-local variable\n"); + return false; + } + if (!strchr(sym->name, '.')) { + return false; } - if (!strchr(sym->name, '.')) - return false; - - /* - * TODO: Special static local variables should never be correlated and should always - * be included if they are referenced by an included function. - */ - - return true; + /* + * TODO: Special static local variables should never be correlated and should always + * be included if they are referenced by an included function. + */ + return true; } int offset_of_string(struct list_head *list, char *name) { - struct string *string; - int index = 0; - - list_for_each_entry(string, list, list) { - if (!strcmp(string->name, name)) - return index; - index += (int)strlen(string->name) + 1; - } - - ALLOC_LINK(string, list); - string->name = name; - return index; + struct string *string; + int index = 0; + + list_for_each_entry(string, list, list) { + if (!strcmp(string->name, name)) { + return index; + } + index += (int)strlen(string->name) + 1; + } + + ALLOC_LINK(string, list); + string->name = name; + + return index; } // no need for X86 bool is_gcc6_localentry_bundled_sym(struct upatch_elf *uelf) { - switch(uelf->arch) { - case AARCH64: - return false; - case X86_64: - return false; - default: - ERROR("unsupported arch"); - } - return false; + switch (uelf->arch) { + case AARCH64: + return false; + case X86_64: + return false; + default: + ERROR("unsupported arch"); + } + + return false; } bool is_mapping_symbol(struct upatch_elf *uelf, struct symbol *sym) { - if (uelf->arch != AARCH64) - return false; - - if (sym->name && sym->name[0] == '$' - && sym->type == STT_NOTYPE - && sym->bind == STB_LOCAL) - return true; - return false; + if (uelf->arch != AARCH64) { + return false; + } + if (sym->name && sym->name[0] == '$' && + sym->type == STT_NOTYPE && + sym->bind == STB_LOCAL) { + return true; + } + + return false; } diff --git a/upatch-diff/elf-common.h b/upatch-diff/elf-common.h index f3d43086..f5a48da6 100644 --- a/upatch-diff/elf-common.h +++ b/upatch-diff/elf-common.h @@ -36,14 +36,16 @@ #include "log.h" #define ALLOC_LINK(_new, _list) \ -{ \ - (_new) = calloc(1, sizeof(*(_new))); \ - if (!(_new)) \ - ERROR("calloc"); \ - INIT_LIST_HEAD(&(_new)->list); \ - if (_list) \ - list_add_tail(&(_new)->list, (_list)); \ -} + do { \ + (_new) = calloc(1, sizeof(*(_new))); \ + if (!(_new)) { \ + ERROR("calloc"); \ + } \ + INIT_LIST_HEAD(&(_new)->list); \ + if (_list) { \ + list_add(&(_new)->list, (_list)); \ + } \ + } while (0) static inline bool is_rela_section(struct section *sec) { @@ -51,120 +53,132 @@ static inline bool is_rela_section(struct section *sec) * An architecture usually only accepts one type. * And, X86_64 only uses RELA */ - return (sec->sh.sh_type == SHT_RELA); + return (sec->sh.sh_type == SHT_RELA); } static inline bool is_text_section(struct section *sec) { - return (sec->sh.sh_type == SHT_PROGBITS && - (sec->sh.sh_flags & SHF_EXECINSTR)); + return (sec->sh.sh_type == SHT_PROGBITS && + (sec->sh.sh_flags & SHF_EXECINSTR)); } static inline bool is_string_section(struct section *sec) { - return sec->sh.sh_flags & SHF_STRINGS; + return sec->sh.sh_flags & SHF_STRINGS; } /* used for c++ exception handle */ static inline bool is_except_section(struct section *sec) { - return !strncmp(sec->name, ".gcc_except_table", 17); + return !strncmp(sec->name, ".gcc_except_table", 17); } static inline bool is_note_section(struct section *sec) { - if (is_rela_section(sec)) - sec = sec->base; - return sec->sh.sh_type == SHT_NOTE; + if (is_rela_section(sec)) { + sec = sec->base; + } + return sec->sh.sh_type == SHT_NOTE; } static inline bool is_eh_frame(struct section *sec) { - char *name; - if (is_rela_section(sec)) - name = sec->base->name; - else - name = sec->name; - - return !strncmp(name, ".eh_frame", 9); + char *name; + if (is_rela_section(sec)) { + name = sec->base->name; + } else { + name = sec->name; + } + return !strncmp(name, ".eh_frame", 9); } static inline bool is_debug_section(struct section *sec) { - char *name; - if (is_rela_section(sec)) - name = sec->base->name; - else - name = sec->name; - - /* .eh_frame_hdr will be generated by the linker */ - return !strncmp(name, ".debug_", 7) || - !strncmp(name, ".eh_frame", 9); + char *name; + if (is_rela_section(sec)) { + name = sec->base->name; + } else { + name = sec->name; + } + /* .eh_frame_hdr will be generated by the linker */ + return !strncmp(name, ".debug_", 7) || + !strncmp(name, ".eh_frame", 9); } static inline struct symbol *find_symbol_by_index(struct list_head *list, unsigned int index) { - struct symbol *sym; + struct symbol *sym; - list_for_each_entry(sym, list, list) - if (sym->index == index) - return sym; + list_for_each_entry(sym, list, list) { + if (sym->index == index) { + return sym; + } + } - return NULL; + return NULL; } static inline struct symbol *find_symbol_by_name(struct list_head *list, const char *name) { - struct symbol *sym; + struct symbol *sym; - list_for_each_entry(sym, list, list) - if (sym->name && !strcmp(sym->name, name)) - return sym; + list_for_each_entry(sym, list, list) { + if (sym->name && !strcmp(sym->name, name)) { + return sym; + } + } - return NULL; + return NULL; } static inline struct section *find_section_by_index(struct list_head *list, unsigned int index) { - struct section *sec; + struct section *sec; - list_for_each_entry(sec, list, list) - if (sec->index == index) - return sec; + list_for_each_entry(sec, list, list) { + if (sec->index == index) { + return sec; + } + } - return NULL; + return NULL; } static inline struct section *find_section_by_name(struct list_head *list, const char *name) { - struct section *sec; + struct section *sec; - list_for_each_entry(sec, list, list) - if (!strcmp(sec->name, name)) - return sec; + list_for_each_entry(sec, list, list) { + if (!strcmp(sec->name, name)) { + return sec; + } + } - return NULL; + return NULL; } // section like .rodata.str1. and .rodata.__func__. static inline bool is_string_literal_section(struct section *sec) { - return !strncmp(sec->name, ".rodata.", 8) && (strstr(sec->name, ".str") || strstr(sec->name, "__func__")); + return !strncmp(sec->name, ".rodata.", 8) && (strstr(sec->name, ".str") || strstr(sec->name, "__func__")); } static inline bool has_digit_tail(char *tail) { - if (*tail != '.') - return false; + if (*tail != '.') { + return false; + } - while (isdigit(*++tail)) - ; + while (isdigit(*++tail)) { + // empty loop body + } - if (!*tail) - return true; + if (!*tail) { + return true; + } - return false; + return false; } /* @@ -178,59 +192,60 @@ bool is_normal_static_local(struct symbol *); static inline char *section_function_name(struct section *sec) { - if (is_rela_section(sec)) - sec = sec->base; - return sec->sym ? sec->sym->name : sec->name; + if (is_rela_section(sec)) { + sec = sec->base; + } + return sec->sym ? sec->sym->name : sec->name; } static inline char *status_str(enum status status) { - switch(status) { - case NEW: - return "NEW"; - case CHANGED: - return "CHANGED"; - case SAME: - return "SAME"; - default: - ERROR("status_str"); - } - return NULL; + switch (status) { + case NEW: + return "NEW"; + case CHANGED: + return "CHANGED"; + case SAME: + return "SAME"; + default: + ERROR("status_str"); + } + return NULL; } int offset_of_string(struct list_head *, char *); static inline unsigned int absolute_rela_type(struct upatch_elf *uelf) { - switch(uelf->arch) { - case AARCH64: - return R_AARCH64_ABS64; - case X86_64: - return R_X86_64_64; - default: - ERROR("unsupported arch"); - } - return 0; + switch (uelf->arch) { + case AARCH64: + return R_AARCH64_ABS64; + case X86_64: + return R_X86_64_64; + default: + ERROR("unsupported arch"); + } + return 0; } static inline bool is_null_sym(struct symbol *sym) { - return !strlen(sym->name); + return !strlen(sym->name); } static inline bool is_file_sym(struct symbol *sym) { - return sym->type == STT_FILE; + return sym->type == STT_FILE; } static inline bool is_local_func_sym(struct symbol *sym) { - return sym->bind == STB_LOCAL && sym->type == STT_FUNC; + return sym->bind == STB_LOCAL && sym->type == STT_FUNC; } static inline bool is_local_sym(struct symbol *sym) { - return sym->bind == STB_LOCAL; + return sym->bind == STB_LOCAL; } bool is_gcc6_localentry_bundled_sym(struct upatch_elf *); @@ -243,4 +258,4 @@ bool is_gcc6_localentry_bundled_sym(struct upatch_elf *); */ bool is_mapping_symbol(struct upatch_elf *, struct symbol *); -#endif \ No newline at end of file +#endif diff --git a/upatch-diff/elf-compare.c b/upatch-diff/elf-compare.c index 5d398250..7ca6845e 100644 --- a/upatch-diff/elf-compare.c +++ b/upatch-diff/elf-compare.c @@ -29,26 +29,26 @@ #include "elf-compare.h" #include "elf-insn.h" -static void compare_correlated_symbol(struct symbol *sym, struct symbol *symtwin) +static void compare_correlated_symbol(struct symbol *sym, + struct symbol *symtwin) { // compare bind and type info if (sym->sym.st_info != symtwin->sym.st_info || - (sym->sec && !symtwin->sec) || - (symtwin->sec && !sym->sec)) - DIFF_FATAL("symbol info mismatch: %s", sym->name); - + (sym->sec && !symtwin->sec) || + (symtwin->sec && !sym->sec)) { + ERROR("symbol info mismatch: %s", sym->name); + } // check if correlated symbols have correlated sections - if (sym->sec && symtwin->sec && sym->sec->twin != symtwin->sec) - DIFF_FATAL("symbol changed sections: %s", sym->name); - + if (sym->sec && symtwin->sec && sym->sec->twin != symtwin->sec) { + ERROR("symbol changed sections: %s", sym->name); + } // data object can't change size - if (sym->type == STT_OBJECT && sym->sym.st_size != symtwin->sym.st_size) - DIFF_FATAL("object size mismatch: %s", sym->name); - - if (sym->sym.st_shndx == SHN_UNDEF || - sym->sym.st_shndx == SHN_ABS) - sym->status = SAME; - + if (sym->type == STT_OBJECT && sym->sym.st_size != symtwin->sym.st_size) { + ERROR("object size mismatch: %s", sym->name); + } + if (sym->sym.st_shndx == SHN_UNDEF || sym->sym.st_shndx == SHN_ABS) { + sym->status = SAME; + } /* * For local symbols, we handle them based on their matching sections. */ @@ -56,323 +56,355 @@ static void compare_correlated_symbol(struct symbol *sym, struct symbol *symtwin void upatch_compare_symbols(struct upatch_elf *uelf) { - struct symbol *sym; - - list_for_each_entry(sym, &uelf->symbols, list) { - if (sym->twin) - compare_correlated_symbol(sym, sym->twin); - else - sym->status = NEW; + struct symbol *sym; - log_debug("symbol %s is %s\n", sym->name, status_str(sym->status)); - } + list_for_each_entry(sym, &uelf->symbols, list) { + if (sym->twin) { + compare_correlated_symbol(sym, sym->twin); + } else { + sym->status = NEW; + } + log_debug("symbol %s is %s\n", sym->name, status_str(sym->status)); + } } static bool rela_equal(struct rela *rela1, struct rela *rela2) { - if (rela1->type != rela2->type || - rela1->offset != rela2->offset) + if (rela1->type != rela2->type || rela1->offset != rela2->offset) { return false; - + } /* TODO: handle altinstr_aux */ - /* TODO: handle rela for toc section */ - - if (rela1->string) - return rela2->string && !strcmp(rela1->string, rela2->string); - - if (rela1->addend != rela2->addend) { - log_debug("relocation addend has changed from %ld to %ld", rela1->addend, rela2->addend); - return false; + if (rela1->string) { + return rela2->string && !strcmp(rela1->string, rela2->string); + } + if (rela1->addend != rela2->addend) { + log_debug("relocation addend has changed from %ld to %ld", + rela1->addend, rela2->addend); + return false; } return !mangled_strcmp(rela1->sym->name, rela2->sym->name); } -static void compare_correlated_rela_section(struct section *relasec, struct section *relasec_twin) +static void compare_correlated_rela_section(struct section *relasec, + struct section *relasec_twin) { - struct rela *rela1, *rela2 = NULL; + struct rela *rela1 = NULL; + struct rela *rela2 = NULL; /* check relocation item one by one, order matters */ - rela2 = list_entry(relasec_twin->relas.next, struct rela, list); - list_for_each_entry(rela1, &relasec->relas, list) { - if (rela_equal(rela1, rela2)) { - rela2 = list_entry(rela2->list.next, struct rela, list); - continue; - } - relasec->status = CHANGED; - return; - } - - relasec->status = SAME; + rela2 = list_entry(relasec_twin->relas.next, struct rela, list); + list_for_each_entry(rela1, &relasec->relas, list) { + if (rela_equal(rela1, rela2)) { + rela2 = list_entry(rela2->list.next, struct rela, list); + continue; + } + relasec->status = CHANGED; + return; + } + relasec->status = SAME; } -static void compare_correlated_nonrela_section(struct section *sec, struct section *sectwin) +static void compare_correlated_nonrela_section(struct section *sec, + struct section *sectwin) { - if (sec->sh.sh_type != SHT_NOBITS && + if (sec->sh.sh_type != SHT_NOBITS && (sec->data->d_size != sectwin->data->d_size || - memcmp(sec->data->d_buf, sectwin->data->d_buf, sec->data->d_size))) - sec->status = CHANGED; - else - sec->status = SAME; + memcmp(sec->data->d_buf, sectwin->data->d_buf, sec->data->d_size))) { + sec->status = CHANGED; + } else { + sec->status = SAME; + } } // we may change status of sec, they are not same -static int compare_correlated_section(struct section *sec, struct section *sectwin) +static int compare_correlated_section(struct section *sec, + struct section *sectwin) { /* TODO: addr align of rodata has changed. after strlen(str) >= 30, align 8 exists */ /* compare section headers */ - if (sec->sh.sh_type != sectwin->sh.sh_type || - sec->sh.sh_flags != sectwin->sh.sh_flags || - sec->sh.sh_entsize != sectwin->sh.sh_entsize || - (sec->sh.sh_addralign != sectwin->sh.sh_addralign && - !is_text_section(sec) && !is_string_section(sec))) { - DIFF_FATAL("%s section header details differ from %s", sec->name, sectwin->name); + if (sec->sh.sh_type != sectwin->sh.sh_type || + sec->sh.sh_flags != sectwin->sh.sh_flags || + sec->sh.sh_entsize != sectwin->sh.sh_entsize || + (sec->sh.sh_addralign != sectwin->sh.sh_addralign && + !is_text_section(sec) && !is_string_section(sec))) { + ERROR("%s section header details differ from %s", + sec->name, sectwin->name); return -1; } - if (is_note_section(sec)) { - sec->status = SAME; - goto out; - } - - /* As above but for aarch64 */ - if (!strcmp(sec->name, ".rela__patchable_function_entries") || - !strcmp(sec->name, "__patchable_function_entries")) { - sec->status = SAME; - goto out; - } - + if (is_note_section(sec)) { + sec->status = SAME; + goto out; + } + /* As above but for aarch64 */ + if (!strcmp(sec->name, ".rela__patchable_function_entries") || + !strcmp(sec->name, "__patchable_function_entries")) { + sec->status = SAME; + goto out; + } /* compare file size and data size(memory size) */ - if (sec->sh.sh_size != sectwin->sh.sh_size || - sec->data->d_size != sectwin->data->d_size || + if (sec->sh.sh_size != sectwin->sh.sh_size || + sec->data->d_size != sectwin->data->d_size || (sec->rela && !sectwin->rela) || (!sec->rela && sectwin->rela)) { - sec->status = CHANGED; - goto out; - } + sec->status = CHANGED; + goto out; + } - if (is_rela_section(sec)) + if (is_rela_section(sec)) { compare_correlated_rela_section(sec, sectwin); - else + } else { compare_correlated_nonrela_section(sec, sectwin); + } out: - if(sec->status == CHANGED) - log_debug("section %s has changed\n", sec->name); + if (sec->status == CHANGED) { + log_debug("section %s has changed\n", sec->name); + } return 0; } bool upatch_handle_redis_line(const char *symname) { - if (!strncmp(symname, "_serverPanic", 12) || - !strncmp(symname, "_serverAssert", 13) || - !strncmp(symname, "_serverAssertWithInfo", 21) || + if (!strncmp(symname, "_serverPanic", 12) || + !strncmp(symname, "_serverAssert", 13) || + !strncmp(symname, "_serverAssertWithInfo", 21) || !strncmp(symname, "rdbReportError", 14) || - !strncmp(symname, "RedisModule__Assert", 19)) - return true; - return false; + !strncmp(symname, "RedisModule__Assert", 19)) { + return true; + } + + return false; } /* TODO: let user support this list or generate by the compiler ? */ bool check_line_func(const char *symname) { - if (!strncmp(basename(g_relf_name), "redis-server", 12)) - return upatch_handle_redis_line(symname); + if (!strncmp(basename(g_relf_name), "redis-server", 12)) { + return upatch_handle_redis_line(symname); + } - return false; + return false; } /* Determine if a section has changed only due to a __LINE__ bumber change. * For example, a WARN() or might_sleep() macro's embedding of the line number into an * instruction operand. */ -static bool _line_macro_change_only(struct upatch_elf *uelf, struct section *sec) +static bool line_macro_change_only_x86_64(struct upatch_elf *uelf, + struct section *sec) { - unsigned long offset, insn1_len, insn2_len; - void *data1, *data2, *insn1, *insn2; - struct rela *rela; - bool found, found_any = false; - - if (sec->status != CHANGED || - is_rela_section(sec) || - !is_text_section(sec) || - sec->sh.sh_size != sec->twin->sh.sh_size || - !sec->rela || - sec->rela->status != SAME) - return false; - - data1 = sec->twin->data->d_buf; - data2 = sec->data->d_buf; - for (offset = 0; offset < sec->sh.sh_size; offset += insn1_len) { - insn1 = data1 + offset; - insn2 = data2 + offset; - - insn1_len = insn_length(uelf, insn1); - insn2_len = insn_length(uelf, insn2); - - if (!insn1_len || !insn2_len) - ERROR("decode instruction in section %s at offset 0x%lx failed", - sec->name, offset); - - if (insn1_len != insn2_len) - return false; - - /* if insn are same, continue*/ - if (!memcmp(insn1, insn2, insn1_len)) - continue; - - log_debug("check list for %s at 0x%lx \n", sec->name, offset); - - /* - * Here we found a differece between two instructions of the - * same length. Only ignore the change if: - * - * 1) the instruction match a known pattern of a '__LINE__' - * macro immediate value which was embedded in the instruction. - * - * 2) the instructions are followed by certain expected relocations. - * (white-list) - */ - if (!insn_is_load_immediate(uelf, insn1) || - !insn_is_load_immediate(uelf, insn2)) - return false; - - found = false; - list_for_each_entry(rela, &sec->rela->relas, list) { - if (rela->offset < offset + insn1_len) - continue; - - if (rela->string) - continue; - - /* TODO: we may need black list ? */ - if (check_line_func(rela->sym->name)) { - found = true; - break; - } - - return false; - } - if (!found) - return false; - - found_any = true; - } - - if (!found_any) - ERROR("no instruction changes detected for changed section %s", - sec->name); + unsigned long offset; + unsigned long insn1_len; + unsigned long insn2_len; + + void *data1; + void *data2; + void *insn1; + void *insn2; + + struct rela *rela = NULL; + bool found_any = false; + bool found = false; + + if (sec->status != CHANGED || + is_rela_section(sec) || + !is_text_section(sec) || + sec->sh.sh_size != sec->twin->sh.sh_size || + !sec->rela || + sec->rela->status != SAME) { + return false; + } + + data1 = sec->twin->data->d_buf; + data2 = sec->data->d_buf; + for (offset = 0; offset < sec->sh.sh_size; offset += insn1_len) { + insn1 = data1 + offset; + insn2 = data2 + offset; + + insn1_len = insn_length(uelf, insn1); + insn2_len = insn_length(uelf, insn2); + if (!insn1_len || !insn2_len) { + ERROR("decode instruction in section %s at offset 0x%lx failed", + sec->name, offset); + } + + if (insn1_len != insn2_len) { + return false; + } + + /* if insn are same, continue */ + if (!memcmp(insn1, insn2, insn1_len)) { + continue; + } + log_debug("check list for %s at 0x%lx\n", sec->name, offset); + + /* + * Here we found a differece between two instructions of the + * same length. Only ignore the change if: + * + * 1) the instruction match a known pattern of a '__LINE__' + * macro immediate value which was embedded in the instruction. + * + * 2) the instructions are followed by certain expected relocations. + * (white-list) + */ + if (!insn_is_load_immediate(uelf, insn1) || + !insn_is_load_immediate(uelf, insn2)) { + return false; + } + + found = false; + list_for_each_entry(rela, &sec->rela->relas, list) { + if (rela->offset < offset + insn1_len) { + continue; + } + if (rela->string) { + continue; + } + /* TODO: we may need black list ? */ + if (check_line_func(rela->sym->name)) { + found = true; + break; + } + return false; + } + if (!found) { + return false; + } + + found_any = true; + } + + if (!found_any) { + ERROR("no instruction changes detected for changed section %s", + sec->name); + } return true; } -static bool _line_macro_change_only_aarch64(struct upatch_elf *uelf, struct section *sec) +static bool line_macro_change_only_aarch64(struct upatch_elf *uelf, + struct section *sec) { + unsigned long start1; + unsigned long start2; + unsigned long size; + unsigned long offset; + + struct rela *rela = NULL; + bool found_any = false; + bool found = false; + + unsigned int mov_imm_mask = ((1<<16) - 1)<<5; + unsigned long insn_len = insn_length(uelf, NULL); + + if (sec->status != CHANGED || + is_rela_section(sec) || + !is_text_section(sec) || + sec->sh.sh_size != sec->twin->sh.sh_size || + !sec->rela || + sec->rela->status != SAME) { + return false; + } + + start1 = (unsigned long)sec->twin->data->d_buf; + start2 = (unsigned long)sec->data->d_buf; + size = sec->sh.sh_size; + for (offset = 0; offset < size; offset += insn_len) { + if (!memcmp((void *)start1 + offset, (void *)start2 + offset, + insn_len)) { + continue; + } + + /* verify it's a mov immediate to w1 */ + if ((*(unsigned int *)(start1 + offset) & ~mov_imm_mask) != + (*(unsigned int *)(start2 + offset) & ~mov_imm_mask)) { + return false; + } + + found = false; + list_for_each_entry(rela, &sec->rela->relas, list) { + if (rela->offset < offset + insn_len) { + continue; + } + if (rela->string) { + continue; + } + /* TODO: we may need black list ? */ + if (check_line_func(rela->sym->name)) { + found = true; + break; + } + return false; + } + if (!found) { + return false; + } - unsigned long start1, start2, size, offset; - struct rela *rela; - bool found_any = false, found; - unsigned int mov_imm_mask = ((1<<16) - 1)<<5; - unsigned long insn_len = insn_length(uelf, NULL); - - if (sec->status != CHANGED || - is_rela_section(sec) || - !is_text_section(sec) || - sec->sh.sh_size != sec->twin->sh.sh_size || - !sec->rela || - sec->rela->status != SAME) - return false; - - start1 = (unsigned long)sec->twin->data->d_buf; - start2 = (unsigned long)sec->data->d_buf; - size = sec->sh.sh_size; - for (offset = 0; offset < size; offset += insn_len) { - if (!memcmp((void *)start1 + offset, (void *)start2 + offset, insn_len)) - continue; - - /* verify it's a mov immediate to w1 */ - if ((*(unsigned int *)(start1 + offset) & ~mov_imm_mask) != - (*(unsigned int *)(start2 + offset) & ~mov_imm_mask)) - return false; - - found = false; - list_for_each_entry(rela, &sec->rela->relas, list) { - if (rela->offset < offset + insn_len) - continue; - if (rela->string) - continue; - - /* TODO: we may need black list ? */ - if (check_line_func(rela->sym->name)) { - found = true; - break; - } - return false; - } - if (!found) - return false; - - found_any = true; - } - - if (!found_any) - ERROR("no instruction changes detected for changed section %s", - sec->name); - - return true; + found_any = true; + } + + if (!found_any) { + ERROR("no instruction changes detected for changed section %s", + sec->name); + } + + return true; } static bool line_macro_change_only(struct upatch_elf *uelf, struct section *sec) { - switch(uelf->arch) { - case AARCH64: - return _line_macro_change_only_aarch64(uelf, sec); - case X86_64: - return _line_macro_change_only(uelf, sec); - default: - ERROR("unsupported arch"); - } - return false; + switch (uelf->arch) { + case AARCH64: + return line_macro_change_only_aarch64(uelf, sec); + case X86_64: + return line_macro_change_only_x86_64(uelf, sec); + default: + ERROR("unsupported arch"); + } + return false; } -static inline void update_section_status(struct section *sec, enum status status) +static void update_section_status(struct section *sec, enum status status) { - if (sec == NULL) { - return; - } - if (sec->twin != NULL) { - sec->twin->status = status; - } - if (is_rela_section(sec)) { - if ((sec->base != NULL) && (sec->base->sym != NULL) && status != SAME) { - sec->base->sym->status = status; - } - } else { - if (sec->sym != NULL) { - sec->sym->status = status; - } - } + if (sec == NULL) { + return; + } + if (sec->twin != NULL) { + sec->twin->status = status; + } + if (is_rela_section(sec)) { + if ((sec->base != NULL) && (sec->base->sym != NULL) && status != SAME) { + sec->base->sym->status = status; + } + } else { + if (sec->sym != NULL) { + sec->sym->status = status; + } + } } void upatch_compare_sections(struct upatch_elf *uelf) { - struct section *sec = NULL; - - list_for_each_entry(sec, &uelf->sections, list) { - if (sec->twin == NULL) { - sec->status = NEW; - } - else { - compare_correlated_section(sec, sec->twin); - } - /* exclude WARN-only, might_sleep changes */ - if (line_macro_change_only(uelf, sec)) { - log_debug("reverting macro / line number section %s status to SAME\n", sec->name); - sec->status = SAME; - } - /* sync status */ - update_section_status(sec, sec->status); - update_section_status(sec->twin, sec->status); - } -} \ No newline at end of file + struct section *sec = NULL; + + list_for_each_entry(sec, &uelf->sections, list) { + if (sec->twin == NULL) { + sec->status = NEW; + } else { + compare_correlated_section(sec, sec->twin); + } + /* exclude WARN-only, might_sleep changes */ + if (line_macro_change_only(uelf, sec)) { + log_debug("reverting line number section %s status to SAME\n", + sec->name); + sec->status = SAME; + } + /* sync status */ + update_section_status(sec, sec->status); + update_section_status(sec->twin, sec->status); + } +} diff --git a/upatch-diff/elf-compare.h b/upatch-diff/elf-compare.h index 3fd46a9d..8ec16552 100644 --- a/upatch-diff/elf-compare.h +++ b/upatch-diff/elf-compare.h @@ -37,4 +37,4 @@ static inline void upatch_compare_correlated_elements(struct upatch_elf *uelf) upatch_compare_symbols(uelf); } -#endif \ No newline at end of file +#endif diff --git a/upatch-diff/elf-correlate.c b/upatch-diff/elf-correlate.c index cc3b925f..979453b4 100644 --- a/upatch-diff/elf-correlate.c +++ b/upatch-diff/elf-correlate.c @@ -27,67 +27,80 @@ #include "elf-common.h" #include "elf-correlate.h" -static void correlate_symbol(struct symbol *sym_orig, struct symbol *sym_patched) +static void correlate_symbol(struct symbol *sym_orig, + struct symbol *sym_patched) { - log_debug("correlate symbol %s <-> %s \n", sym_orig->name, sym_patched->name); + log_debug("correlate symbol %s <-> %s\n", + sym_orig->name, sym_patched->name); sym_orig->twin = sym_patched; sym_patched->twin = sym_orig; sym_orig->status = sym_patched->status = SAME; if (strcmp(sym_orig->name, sym_patched->name)) { - log_debug("renaming symbol %s to %s \n", sym_patched->name, sym_orig->name); + log_debug("renaming symbol %s to %s\n", + sym_patched->name, sym_orig->name); sym_patched->name = sym_orig->name; sym_patched->name_source = DATA_SOURCE_REF; } - if (sym_orig->relf_sym && !sym_patched->relf_sym) - sym_patched->relf_sym = sym_orig->relf_sym; + if (sym_orig->relf_sym && !sym_patched->relf_sym) { + sym_patched->relf_sym = sym_orig->relf_sym; + } } -void upatch_correlate_symbols(struct upatch_elf *uelf_source, struct upatch_elf *uelf_patched) +void upatch_correlate_symbols(struct upatch_elf *uelf_source, + struct upatch_elf *uelf_patched) { - struct symbol *sym_orig, *sym_patched; - - list_for_each_entry(sym_orig, &uelf_source->symbols, list) { - if (sym_orig->twin) - continue; + struct symbol *sym_orig; + struct symbol *sym_patched; + list_for_each_entry(sym_orig, &uelf_source->symbols, list) { + if (sym_orig->twin) { + continue; + } /* find matched symbol */ - list_for_each_entry(sym_patched, &uelf_patched->symbols, list) { - if (mangled_strcmp(sym_orig->name, sym_patched->name) || - sym_orig->type != sym_patched->type || sym_patched->twin) - continue; - - /* - * TODO: Special static local variables should never be correlated and should always - * be included if they are referenced by an included function. - */ - /* - * The .LCx symbols point to string literals in - * '.rodata..str1.*' sections. They get included - * in include_standard_elements(). - * Clang creates similar .Ltmp%d symbols in .rodata.str - */ - if (sym_orig->type == STT_NOTYPE && - (!strncmp(sym_orig->name, ".LC", 3) || !strncmp(sym_orig->name, ".Ltmp", 5))) - continue; - - if (is_mapping_symbol(uelf_source, sym_orig)) - continue; - - /* group section symbols must have correlated sections */ - if (sym_orig->sec && sym_orig->sec->sh.sh_type == SHT_GROUP && - sym_orig->sec->twin != sym_patched->sec) - continue; - - correlate_symbol(sym_orig, sym_patched); - break; - } - } + list_for_each_entry(sym_patched, &uelf_patched->symbols, list) { + if (mangled_strcmp(sym_orig->name, sym_patched->name) || + sym_orig->type != sym_patched->type || sym_patched->twin) { + continue; + } + /* + * TODO: Special static local variables should never be correlated + * and should always be included if they are referenced by + * an included function. + */ + /* + * The .LCx symbols point to string literals in + * '.rodata..str1.*' sections. They get included + * in include_standard_elements(). + * Clang creates similar .Ltmp%d symbols in .rodata.str + */ + if (sym_orig->type == STT_NOTYPE && + (!strncmp(sym_orig->name, ".LC", 3) || + !strncmp(sym_orig->name, ".Ltmp", 5))) { + continue; + } + + if (is_mapping_symbol(uelf_source, sym_orig)) { + continue; + } + + /* group section symbols must have correlated sections */ + if (sym_orig->sec && sym_orig->sec->sh.sh_type == SHT_GROUP && + sym_orig->sec->twin != sym_patched->sec) { + continue; + } + + correlate_symbol(sym_orig, sym_patched); + break; + } + } } -static void __correlate_section(struct section *sec_orig, struct section *sec_patched) +static void correlate_section_impl(struct section *sec_orig, + struct section *sec_patched) { - log_debug("correlate section %s <-> %s \n", sec_orig->name, sec_patched->name); + log_debug("correlate section %s <-> %s\n", + sec_orig->name, sec_patched->name); sec_orig->twin = sec_patched; sec_patched->twin = sec_orig; @@ -96,96 +109,104 @@ static void __correlate_section(struct section *sec_orig, struct section *sec_pa /* Make sure these two sections have the same name */ if (strcmp(sec_orig->name, sec_patched->name)) { - log_debug("renaming section %s to %s \n", sec_patched->name, sec_orig->name); + log_debug("renaming section %s to %s\n", + sec_patched->name, sec_orig->name); sec_patched->name = sec_orig->name; sec_patched->name_source = DATA_SOURCE_REF; } } -static void correlate_section(struct section *sec_orig, struct section *sec_patched) +static void correlate_section(struct section *sec_orig, + struct section *sec_patched) { - __correlate_section(sec_orig, sec_patched); - - if (is_rela_section(sec_orig)) { - __correlate_section(sec_orig->base, sec_patched->base); + correlate_section_impl(sec_orig, sec_patched); + if (is_rela_section(sec_orig)) { + correlate_section_impl(sec_orig->base, sec_patched->base); /* handle symbol for base section now */ - sec_orig = sec_orig->base; - sec_patched = sec_patched->base; - } else if (sec_orig->rela && sec_patched->rela) { - __correlate_section(sec_orig->rela, sec_patched->rela); - } - - if (sec_orig->secsym && sec_patched->secsym) { - correlate_symbol(sec_orig->secsym, sec_patched->secsym); - } - - if (sec_orig->sym) { - correlate_symbol(sec_orig->sym, sec_patched->sym); - } + sec_orig = sec_orig->base; + sec_patched = sec_patched->base; + } else if (sec_orig->rela && sec_patched->rela) { + correlate_section_impl(sec_orig->rela, sec_patched->rela); + } + if (sec_orig->secsym && sec_patched->secsym) { + correlate_symbol(sec_orig->secsym, sec_patched->secsym); + } + if (sec_orig->sym) { + correlate_symbol(sec_orig->sym, sec_patched->sym); + } } -void upatch_correlate_sections(struct upatch_elf *uelf_source, struct upatch_elf *uelf_patched) +void upatch_correlate_sections(struct upatch_elf *uelf_source, + struct upatch_elf *uelf_patched) { - struct section *sec_orig, *sec_patched; + struct section *sec_orig; + struct section *sec_patched; - list_for_each_entry(sec_orig, &uelf_source->sections, list) { + list_for_each_entry(sec_orig, &uelf_source->sections, list) { /* already found */ - if (sec_orig->twin) - continue; - - list_for_each_entry(sec_patched, &uelf_patched->sections, list) { - if (mangled_strcmp(sec_orig->name, sec_patched->name) || - sec_patched->twin) - continue; - - /* - * TODO: Special static local variables should never be correlated and should always - * be included if they are referenced by an included function. - */ - /* - * Group sections must match exactly to be correlated. - */ - if (sec_orig->sh.sh_type == SHT_GROUP) { - if (sec_orig->data->d_size != sec_patched->data->d_size) - continue; - if (memcmp(sec_orig->data->d_buf, sec_patched->data->d_buf, - sec_orig->data->d_size)) - continue; - } - - correlate_section(sec_orig, sec_patched); - break; - } - } + if (sec_orig->twin) { + continue; + } + list_for_each_entry(sec_patched, &uelf_patched->sections, list) { + if (mangled_strcmp(sec_orig->name, sec_patched->name) || + sec_patched->twin) { + continue; + } + /* + * TODO: Special static local variables should never be correlated + * and should always be included if they are referenced by + * an included function. + */ + /* + * Group sections must match exactly to be correlated. + */ + if (sec_orig->sh.sh_type == SHT_GROUP) { + if (sec_orig->data->d_size != sec_patched->data->d_size) { + continue; + } + if (memcmp(sec_orig->data->d_buf, sec_patched->data->d_buf, + sec_orig->data->d_size)) { + continue; + } + } + + correlate_section(sec_orig, sec_patched); + break; + } + } } /* TODO: need handle .toc section */ -static struct symbol *find_uncorrelated_rela(struct section *relasec, struct symbol *sym) +static struct symbol *find_uncorrelated_rela(struct section *relasec, + struct symbol *sym) { - struct rela *rela; - - /* find the patched object's corresponding variable */ - list_for_each_entry(rela, &relasec->relas, list) { - struct symbol *patched_sym = rela->sym; - if (patched_sym->twin) - continue; + struct rela *rela; - if (sym->type != patched_sym->type || - (sym->type == STT_OBJECT && - sym->sym.st_size != patched_sym->sym.st_size)) - continue; + /* find the patched object's corresponding variable */ + list_for_each_entry(rela, &relasec->relas, list) { + struct symbol *patched_sym = rela->sym; - if (mangled_strcmp(patched_sym->name, sym->name)) - continue; + if (patched_sym->twin) { + continue; + } + if (sym->type != patched_sym->type || + ( + sym->type == STT_OBJECT && + sym->sym.st_size != patched_sym->sym.st_size + )) { + continue; + } + if (mangled_strcmp(patched_sym->name, sym->name)) { + continue; + } - log_debug("find uncorrelated rela symbol successful %s [%s] \n", + log_debug("find uncorrelated rela symbol successful %s [%s]\n", patched_sym->name, section_function_name(relasec)); + return patched_sym; + } - return patched_sym; - } - - return NULL; + return NULL; } /* @@ -193,27 +214,30 @@ static struct symbol *find_uncorrelated_rela(struct section *relasec, struct sym * in the base object, find a corresponding usage of a similarly named symbol * in the patched object. */ -static struct symbol *find_static_twin(struct section *relasec, struct symbol *sym) +static struct symbol *find_static_twin(struct section *relasec, + struct symbol *sym) { /* TODO: handle .part symbol is neccessry */ + if (!relasec->twin) { + return NULL; + } - if (!relasec->twin) - return NULL; - - return find_uncorrelated_rela(relasec->twin, sym); + return find_uncorrelated_rela(relasec->twin, sym); } -static struct rela *find_static_twin_ref(struct section *relasec, struct symbol *sym) +static struct rela *find_static_twin_ref(struct section *relasec, + struct symbol *sym) { - struct rela *rela; + struct rela *rela; - list_for_each_entry(rela, &relasec->relas, list) { - if (rela->sym == sym->twin) - return rela; - } + list_for_each_entry(rela, &relasec->relas, list) { + if (rela->sym == sym->twin) { + return rela; + } + } - /* TODO: handle child func here */ - return NULL; + /* TODO: handle child func here */ + return NULL; } /* Check two things: @@ -222,58 +246,65 @@ static struct rela *find_static_twin_ref(struct section *relasec, struct symbol * a corresponding reference in the patched object * (because a staticlocal can be referenced by more than one section) */ -static void check_static_variable_correlate(struct upatch_elf *uelf_source, struct upatch_elf *uelf_patched) +static void check_static_variable_correlate(struct upatch_elf *uelf_source, + struct upatch_elf *uelf_patched) { - struct section *relasec; - struct rela *rela; + struct section *relasec; + struct rela *rela; struct symbol *sym; - list_for_each_entry(relasec, &uelf_source->sections, list) { - if (!is_rela_section(relasec) || - is_debug_section(relasec) || - is_note_section(relasec)) - continue; + list_for_each_entry(relasec, &uelf_source->sections, list) { + if (!is_rela_section(relasec) || + is_debug_section(relasec) || + is_note_section(relasec)) { + continue; + } - list_for_each_entry(rela, &relasec->relas, list) { + list_for_each_entry(rela, &relasec->relas, list) { sym = rela->sym; - if (!is_normal_static_local(sym)) - continue; - - if (!sym->twin || !relasec->twin) - DIFF_FATAL("reference to static local variable %s in %s was removed", + if (!is_normal_static_local(sym)) { + continue; + } + if (!sym->twin || !relasec->twin) { + ERROR("reference to static local variable %s in %s was removed", sym->name, section_function_name(relasec)); - - if(!find_static_twin_ref(relasec->twin, sym)) - DIFF_FATAL("static local %s has been correlated with %s, but patched %s is missing a reference to it", - sym->name, sym->twin->name, section_function_name(relasec->twin)); + } + if (!find_static_twin_ref(relasec->twin, sym)) { + ERROR("static local %s has been correlated with %s, " + "but patched %s is missing a reference to it", + sym->name, sym->twin->name, + section_function_name(relasec->twin)); + } } } - /* - * Now go through the patched object and look for any uncorrelated - * static locals to see if we need to print any warnings about new - * variables. - */ - - list_for_each_entry(relasec, &uelf_patched->sections, list) { - - if (!is_rela_section(relasec) || - is_debug_section(relasec) || - is_note_section(relasec)) - continue; - - list_for_each_entry(rela, &relasec->relas, list) { - sym = rela->sym; - if (!is_normal_static_local(sym)) - continue; + /* + * Now go through the patched object and look for any uncorrelated + * static locals to see if we need to print any warnings about new + * variables. + */ + + list_for_each_entry(relasec, &uelf_patched->sections, list) { + if (!is_rela_section(relasec) || + is_debug_section(relasec) || + is_note_section(relasec)) { + continue; + } - if (sym->twin) - continue; + list_for_each_entry(rela, &relasec->relas, list) { + sym = rela->sym; - log_normal("unable to correlate static local variable %s used by %s, assuming variable is new \n", - sym->name, section_function_name(relasec)); - } - } + if (!is_normal_static_local(sym)) { + continue; + } + if (sym->twin) { + continue; + } + log_normal("unable to correlate static local variable %s used by %s" + ", assuming variable is new\n", + sym->name, section_function_name(relasec)); + } + } } static void uncorrelate_symbol(struct symbol *sym) @@ -312,88 +343,104 @@ static void uncorrelate_section(struct section *sec) * they can occasionally be referenced by data sections as * well. */ -void upatch_correlate_static_local_variables(struct upatch_elf *uelf_source, struct upatch_elf *uelf_patched) +void upatch_correlate_static_local_variables(struct upatch_elf *uelf_source, + struct upatch_elf *uelf_patched) { - struct symbol *sym, *patched_sym; - struct section *relasec; - struct rela *rela; - int bundled, patched_bundled; - - /* - * undo the correlations for all static locals. Two static locals can have the same numbered suffix in the orig - * and patchedobjects by coincidence. - */ - list_for_each_entry(sym, &uelf_source->symbols, list) { - if (!is_normal_static_local(sym)) - continue; + struct symbol *sym; + struct symbol *patched_sym; - log_debug("find normal symbol %s \n", sym->name); - if (sym->twin) - uncorrelate_symbol(sym); + struct section *relasec; + struct rela *rela; - bundled = (sym == sym->sec->sym) ? 1 : 0; - if (bundled && sym->sec->twin) { - log_debug("find bundled static symbol %s \n", sym->name); + int bundled; + int patched_bundled; - uncorrelate_section(sym->sec); + /* + * undo the correlations for all static locals. + * Two static locals can have the same numbered suffix in the orig + * and patchedobjects by coincidence. + */ + list_for_each_entry(sym, &uelf_source->symbols, list) { + if (!is_normal_static_local(sym)) { + continue; + } - if (sym->sec->secsym) - uncorrelate_symbol(sym->sec->secsym); + log_debug("find normal symbol %s\n", sym->name); + if (sym->twin) { + uncorrelate_symbol(sym); + } - if (sym->sec->rela) - uncorrelate_section(sym->sec->rela); // uncorrelate relocation section which is not equal to reference - } - } + bundled = (sym == sym->sec->sym) ? 1 : 0; + if (bundled && sym->sec->twin) { + log_debug("find bundled static symbol %s\n", sym->name); + + uncorrelate_section(sym->sec); + if (sym->sec->secsym) { + uncorrelate_symbol(sym->sec->secsym); + } + if (sym->sec->rela) { + // uncorrelate relocation section which not equals to reference + uncorrelate_section(sym->sec->rela); + } + } + } /* - * Do the correlations: for each section reference to a static local, - * look for a corresponding reference in the section's twin. - */ - list_for_each_entry(relasec, &uelf_source->sections, list) { - + * Do the correlations: for each section reference to a static local, + * look for a corresponding reference in the section's twin. + */ + list_for_each_entry(relasec, &uelf_source->sections, list) { /* handle .rela.toc sectoins */ - if (!is_rela_section(relasec) || - is_debug_section(relasec) || - is_note_section(relasec)) - continue; + if (!is_rela_section(relasec) || + is_debug_section(relasec) || + is_note_section(relasec)) { + continue; + } /* check all relocation symbols */ - list_for_each_entry(rela, &relasec->relas, list) { + list_for_each_entry(rela, &relasec->relas, list) { sym = rela->sym; - if (!is_normal_static_local(sym)) - continue; - - if (sym->twin) - continue; - - bundled = (sym == sym->sec->sym) ? 1 : 0; - if (bundled && sym->sec == relasec->base) { - /* - * TODO: A rare case where a static local data structure references itself. - * There's no reliable way to correlate this. Hopefully - * to the symbol somewhere that can be used. - */ - log_debug("can't correlate static local %s's reference to itself\n", sym->name); - continue; - } - - patched_sym = find_static_twin(relasec, sym); - if (!patched_sym) - DIFF_FATAL("reference to static local variable %s in %s was removed", + if (!is_normal_static_local(sym)) { + continue; + } + if (sym->twin) { + continue; + } + + bundled = (sym == sym->sec->sym) ? 1 : 0; + if (bundled && sym->sec == relasec->base) { + /* + * TODO: + * A rare case where a static local data structure references + * itself. + * There's no reliable way to correlate this. + * Hopefully to the symbol somewhere that can be used. + */ + log_debug("can't correlate static local %s's ref to itself\n", + sym->name); + continue; + } + + patched_sym = find_static_twin(relasec, sym); + if (!patched_sym) { + ERROR("reference to static local variable %s in %s was removed", sym->name, section_function_name(relasec)); - - patched_bundled = (patched_sym == patched_sym->sec->sym) ? 1 : 0; - if (bundled != patched_bundled) - ERROR("bundle mismatch for symbol %s", sym->name); - if (!bundled && sym->sec->twin != patched_sym->sec) - ERROR("sections %s and %s aren't correlated for symbol %s", - sym->sec->name, patched_sym->sec->name, sym->name); - - correlate_symbol(sym, patched_sym); - - if (bundled) - correlate_section(sym->sec, patched_sym->sec); + } + + patched_bundled = (patched_sym == patched_sym->sec->sym) ? 1 : 0; + if (bundled != patched_bundled) { + ERROR("bundle mismatch for symbol %s", sym->name); + } + if (!bundled && sym->sec->twin != patched_sym->sec) { + ERROR("sections %s and %s aren't correlated for symbol %s", + sym->sec->name, patched_sym->sec->name, sym->name); + } + + correlate_symbol(sym, patched_sym); + if (bundled) { + correlate_section(sym->sec, patched_sym->sec); + } } } diff --git a/upatch-diff/elf-correlate.h b/upatch-diff/elf-correlate.h index 21220301..820d07ad 100644 --- a/upatch-diff/elf-correlate.h +++ b/upatch-diff/elf-correlate.h @@ -39,4 +39,4 @@ static inline void upatch_correlate_elf(struct upatch_elf *uelf_source, struct u void upatch_correlate_static_local_variables(struct upatch_elf *, struct upatch_elf *); -#endif \ No newline at end of file +#endif diff --git a/upatch-diff/elf-create.c b/upatch-diff/elf-create.c index bd7edf0f..20d1994c 100644 --- a/upatch-diff/elf-create.c +++ b/upatch-diff/elf-create.c @@ -40,7 +40,8 @@ static struct section *create_section_pair(struct upatch_elf *uelf, char *name, unsigned int entsize, unsigned int nr) { char *relaname; - struct section *sec, *relasec; + struct section *sec; + struct section *relasec; size_t size = strlen(name) + strlen(".rela") + 1; relaname = calloc(1, size); @@ -136,14 +137,21 @@ void upatch_create_strings_elements(struct upatch_elf *uelf) } /* create upatch func info section */ -void upatch_create_patches_sections(struct upatch_elf *uelf, struct running_elf *relf) +void upatch_create_patches_sections(struct upatch_elf *uelf, + struct running_elf *relf) { - struct symbol *sym, *strsym; - struct section *sec, *relasec; + struct symbol *sym; + struct symbol *strsym; + + struct section *sec; + struct section *relasec; + struct upatch_patch_func *funcs; struct rela *rela; struct lookup_result symbol; - unsigned int nr = 0, index = 0; + + unsigned int nr = 0; + unsigned int index = 0; /* find changed func */ list_for_each_entry(sym, &uelf->symbols, list) { @@ -167,15 +175,12 @@ void upatch_create_patches_sections(struct upatch_elf *uelf, struct running_elf if (sym->type != STT_FUNC || sym->status != CHANGED || sym->parent) { continue; } - if (!lookup_relf(relf, sym, &symbol)) { ERROR("Cannot find symbol '%s' in %s", sym->name, g_relf_name); } - if (sym->bind == STB_LOCAL && symbol.global) { ERROR("Cannot find local symbol '%s' in symbol table.", sym->name); } - log_debug("lookup for %s: symbol name %s sympos=%lu size=%lu.\n", sym->name, symbol.symbol->name, symbol.sympos, symbol.symbol->size); @@ -185,7 +190,8 @@ void upatch_create_patches_sections(struct upatch_elf *uelf, struct running_elf funcs[index].new_size = sym->sym.st_size; funcs[index].sympos = symbol.sympos; - log_debug("change func %s from 0x%lx.\n", sym->name, funcs[index].old_addr); + log_debug("change func %s from 0x%lx.\n", + sym->name, funcs[index].old_addr); /* Add a rela than will handle funcs[index].new_addr */ ALLOC_LINK(rela, &relasec->relas); @@ -205,18 +211,20 @@ void upatch_create_patches_sections(struct upatch_elf *uelf, struct running_elf index++; } - if (index != nr) - ERROR("sanity check failed in funcs sections. \n"); + if (index != nr) { + ERROR("sanity check failed in funcs sections.\n"); + } } -static bool need_dynrela(struct running_elf *relf, - struct section *relasec, struct rela *rela) +static bool need_dynrela(struct running_elf *relf, struct section *relasec, + struct rela *rela) { struct lookup_result symbol; if (is_debug_section(relasec) || - is_note_section(relasec)) + is_note_section(relasec)) { return false; + } if (!lookup_relf(relf, rela->sym, &symbol)) { /* relocation is based on new symbol. */ @@ -224,8 +232,9 @@ static bool need_dynrela(struct running_elf *relf, } if (rela->sym->bind == STB_LOCAL) { - if (symbol.global) - ERROR("No releated local symbol found. \n"); + if (symbol.global) { + ERROR("No releated local symbol found.\n"); + } return true; } @@ -239,7 +248,8 @@ static bool need_dynrela(struct running_elf *relf, * 1. refer to old symbols * */ -void upatch_create_intermediate_sections(struct upatch_elf *uelf, struct running_elf *relf) +void upatch_create_intermediate_sections(struct upatch_elf *uelf, + struct running_elf *relf) { struct rela *rela, *rela_safe; struct section *relasec, *usym_sec, *urela_sec; @@ -249,24 +259,27 @@ void upatch_create_intermediate_sections(struct upatch_elf *uelf, struct running unsigned int nr = 0, index = 0; list_for_each_entry(relasec, &uelf->sections, list) { - if (!is_rela_section(relasec)) + if (!is_rela_section(relasec)) { continue; + } /* no need to handle upatch meta section. */ - if (!strcmp(relasec->name, ".rela.upatch.funcs")) + if (!strcmp(relasec->name, ".rela.upatch.funcs")) { continue; - + } list_for_each_entry(rela, &relasec->relas, list) { nr++; - if (need_dynrela(relf, relasec, rela)){ + if (need_dynrela(relf, relasec, rela)) { rela->need_dynrela = 1; } } } - urela_sec = create_section_pair(uelf, ".upatch.relocations", sizeof(*urelas), nr); + urela_sec = create_section_pair(uelf, ".upatch.relocations", + sizeof(*urelas), nr); urelas = urela_sec->data->d_buf; - usym_sec = create_section_pair(uelf, ".upatch.symbols", sizeof(*usyms), nr); + usym_sec = create_section_pair(uelf, ".upatch.symbols", + sizeof(*usyms), nr); usyms = usym_sec->data->d_buf; ALLOC_LINK(usym_sec_sym, &uelf->symbols); @@ -277,17 +290,19 @@ void upatch_create_intermediate_sections(struct upatch_elf *uelf, struct running usym_sec_sym->name = ".upatch.symbols"; strsym = find_symbol_by_name(&uelf->symbols, ".upatch.strings"); - if (!strsym) - ERROR("can't find .upatch.strings symbol. \n"); + if (!strsym) { + ERROR("can't find .upatch.strings symbol.\n"); + } list_for_each_entry(relasec, &uelf->sections, list) { - if (!is_rela_section(relasec)) + if (!is_rela_section(relasec)) { continue; + } if (!strcmp(relasec->name, ".rela.upatch.funcs") || !strcmp(relasec->name, ".rela.upatch.relocations") || - !strcmp(relasec->name, ".rela.upatch.symbols")) + !strcmp(relasec->name, ".rela.upatch.symbols")) { continue; - + } list_for_each_entry_safe(rela, rela_safe, &relasec->relas, list) { if (!rela->need_dynrela) { rela->sym->strip = SYMBOL_USED; @@ -314,12 +329,14 @@ void upatch_build_strings_section_data(struct upatch_elf *uelf) char *strtab; sec = find_section_by_name(&uelf->sections, ".upatch.strings"); - if (!sec) + if (!sec) { ERROR("can't find strings section."); + } size = 0; - list_for_each_entry(string, &uelf->strings, list) + list_for_each_entry(string, &uelf->strings, list) { size += strlen(string->name) + 1; + } /* allocate section resources */ strtab = calloc(1, size); @@ -345,9 +362,9 @@ static void migrate_symbols(struct list_head *src, struct symbol *sym, *sym_safe; list_for_each_entry_safe(sym, sym_safe, src, list) { - if (select && !select(sym)) + if (select && !select(sym)) { continue; - + } list_del(&sym->list); list_add_tail(&sym->list, dst); } @@ -402,9 +419,9 @@ void upatch_reindex_elements(struct upatch_elf *uelf) list_for_each_entry(sym, &uelf->symbols, list) { sym->index = index; index++; - if (sym->sec) + if (sym->sec) { sym->sym.st_shndx = (unsigned short)sym->sec->index; - else if (sym->sym.st_shndx != SHN_ABS) { + } else if (sym->sym.st_shndx != SHN_ABS) { sym->sym.st_shndx = SHN_UNDEF; } } @@ -415,10 +432,13 @@ static void rebuild_rela_section_data(struct section *sec) struct rela *rela; GElf_Rela *relas; size_t size; - unsigned int nr = 0, index = 0; - list_for_each_entry(rela, &sec->relas, list) + unsigned int nr = 0; + unsigned int index = 0; + + list_for_each_entry(rela, &sec->relas, list) { nr++; + } size = nr * sizeof(*relas); relas = calloc(1, size); @@ -438,22 +458,26 @@ static void rebuild_rela_section_data(struct section *sec) index++; } - if (index != nr) + if (index != nr) { ERROR("size mismatch in rebuild rela section."); + } } /* update index for relocations */ void upatch_rebuild_relocations(struct upatch_elf *uelf) { - struct section *relasec, *symtab; + struct section *relasec; + struct section *symtab; symtab = find_section_by_name(&uelf->sections, ".symtab"); - if (!symtab) - ERROR("missing .symtab section in rebuild relocations. \n"); + if (!symtab) { + ERROR("missing .symtab section in rebuild relocations.\n"); + } list_for_each_entry(relasec, &uelf->sections, list) { - if (!is_rela_section(relasec)) + if (!is_rela_section(relasec)) { continue; + } relasec->sh.sh_link = (Elf64_Word)symtab->index; relasec->sh.sh_info = (Elf64_Word)relasec->base->index; rebuild_rela_section_data(relasec); @@ -471,18 +495,23 @@ static void print_strtab(char *buf, size_t size) size_t i; for (i = 0; i < size; i++) { - if (buf[i] == 0) + if (buf[i] == 0) { log_debug("\\0"); - else + } else { log_debug("%c", buf[i]); + } } } void upatch_create_shstrtab(struct upatch_elf *uelf) { - size_t size, offset, len; - struct section *shstrtab, *sec; + struct section *shstrtab; + struct section *sec; + char *buf; + size_t size; + size_t offset; + size_t len; shstrtab = find_section_by_name(&uelf->sections, ".shstrtab"); if (!shstrtab) { @@ -491,8 +520,9 @@ void upatch_create_shstrtab(struct upatch_elf *uelf) /* determine size of string table */ size = 1; - list_for_each_entry(sec, &uelf->sections, list) + list_for_each_entry(sec, &uelf->sections, list) { size += strlen(sec->name) + 1; + } buf = calloc(1, size); if (!buf) { @@ -520,13 +550,16 @@ void upatch_create_shstrtab(struct upatch_elf *uelf) print_strtab(buf, size); log_debug("\n"); - list_for_each_entry(sec, &uelf->sections, list) + list_for_each_entry(sec, &uelf->sections, list) { log_debug("%s @ shstrtab offset %d\n", sec->name, sec->sh.sh_name); + } } void upatch_create_strtab(struct upatch_elf *uelf) { - size_t size = 0, offset = 0, len = 0; + size_t size = 0; + size_t offset = 0; + size_t len = 0; struct section *strtab = find_section_by_name(&uelf->sections, ".strtab"); if (!strtab) { @@ -535,8 +568,9 @@ void upatch_create_strtab(struct upatch_elf *uelf) struct symbol *sym = NULL; list_for_each_entry(sym, &uelf->symbols, list) { - if (sym->type == STT_SECTION) + if (sym->type == STT_SECTION) { continue; + } size += strlen(sym->name) + 1; } @@ -569,8 +603,9 @@ void upatch_create_strtab(struct upatch_elf *uelf) print_strtab(buf, size); log_debug("\n"); - list_for_each_entry(sym, &uelf->symbols, list) + list_for_each_entry(sym, &uelf->symbols, list) { log_debug("%s @ strtab offset %d\n", sym->name, sym->sym.st_name); + } } void upatch_create_symtab(struct upatch_elf *uelf) @@ -578,17 +613,22 @@ void upatch_create_symtab(struct upatch_elf *uelf) struct section *symtab; struct section *strtab; struct symbol *sym; - size_t size; + + unsigned int nr = 0; + unsigned int nr_local = 0; + char *buf; - unsigned int nr = 0, nr_local = 0; + size_t size; unsigned long offset = 0; symtab = find_section_by_name(&uelf->sections, ".symtab"); - if (!symtab) + if (!symtab) { ERROR("find_section_by_name failed."); + } - list_for_each_entry(sym, &uelf->symbols, list) + list_for_each_entry(sym, &uelf->symbols, list) { nr++; + } size = nr * symtab->sh.sh_entsize; buf = calloc(1, size); @@ -600,9 +640,9 @@ void upatch_create_symtab(struct upatch_elf *uelf) list_for_each_entry(sym, &uelf->symbols, list) { memcpy(buf + offset, &sym->sym, symtab->sh.sh_entsize); offset += symtab->sh.sh_entsize; - - if (is_local_sym(sym)) + if (is_local_sym(sym)) { nr_local++; + } } symtab->data->d_buf = buf; @@ -611,38 +651,52 @@ void upatch_create_symtab(struct upatch_elf *uelf) /* update symtab section header */ strtab = find_section_by_name(&uelf->sections, ".strtab"); - if (!strtab) + if (!strtab) { ERROR("missing .strtab section in create symtab."); + } symtab->sh.sh_link = (Elf64_Word)strtab->index; symtab->sh.sh_info = nr_local; } -void upatch_write_output_elf(struct upatch_elf *uelf, Elf *elf, char *outfile, mode_t mode) +void upatch_write_output_elf(struct upatch_elf *uelf, Elf *elf, + char *outfile, mode_t mode) { int fd; + Elf *elfout; + Elf_Scn *scn; Elf_Data *data; - GElf_Ehdr eh, ehout; + + GElf_Ehdr eh; + GElf_Ehdr ehout; + GElf_Shdr sh; - struct section *sec, *shstrtab; + + struct section *sec; + struct section *shstrtab; fd = creat(outfile, mode); - if (fd == -1) + if (fd == -1) { ERROR("creat failed."); + } elfout = elf_begin(fd, ELF_C_WRITE, NULL); - if (!elfout) + if (!elfout) { ERROR("elf_begin failed."); + } /* alloc ELF header */ - if (!gelf_newehdr(elfout, gelf_getclass(elf))) + if (!gelf_newehdr(elfout, gelf_getclass(elf))) { ERROR("gelf_newehdr failed."); - if (!gelf_getehdr(elfout, &ehout)) + } + if (!gelf_getehdr(elfout, &ehout)) { ERROR("gelf_getehdr elfout failed."); - if (!gelf_getehdr(elf, &eh)) + } + if (!gelf_getehdr(elf, &eh)) { ERROR("gelf_getehdr elf failed."); + } memset(&ehout, 0, sizeof(ehout)); ehout.e_ident[EI_DATA] = eh.e_ident[EI_DATA]; @@ -651,43 +705,51 @@ void upatch_write_output_elf(struct upatch_elf *uelf, Elf *elf, char *outfile, m ehout.e_version = EV_CURRENT; shstrtab = find_section_by_name(&uelf->sections, ".shstrtab"); - if (!shstrtab) + if (!shstrtab) { ERROR("missing .shstrtab sections in write output elf"); + } ehout.e_shstrndx = (unsigned short)shstrtab->index; /* add changed sections */ list_for_each_entry(sec, &uelf->sections, list) { scn = elf_newscn(elfout); - if (!scn) + if (!scn) { ERROR("elf_newscn failed."); + } data = elf_newdata(scn); - if (!data) + if (!data) { ERROR("elf_newdata failed."); + } - if (!elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY)) + if (!elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY)) { ERROR("elf_flagdata failed."); + } data->d_type = sec->data->d_type; data->d_buf = sec->data->d_buf; data->d_size = sec->data->d_size; - if (!gelf_getshdr(scn, &sh)) + if (!gelf_getshdr(scn, &sh)) { ERROR("gelf_getshdr in adding changed sections"); + } sh = sec->sh; - if (!gelf_update_shdr(scn, &sh)) + if (!gelf_update_shdr(scn, &sh)) { ERROR("gelf_update_shdr failed."); + } } - if (!gelf_update_ehdr(elfout, &ehout)) + if (!gelf_update_ehdr(elfout, &ehout)) { ERROR("gelf_update_ehdr failed."); + } - if (elf_update(elfout, ELF_C_WRITE) < 0) + if (elf_update(elfout, ELF_C_WRITE) < 0) { ERROR("elf_update failed."); + } elf_end(elfout); close(fd); -} \ No newline at end of file +} diff --git a/upatch-diff/elf-create.h b/upatch-diff/elf-create.h index ce7f263a..b9efbb35 100644 --- a/upatch-diff/elf-create.h +++ b/upatch-diff/elf-create.h @@ -55,4 +55,4 @@ void upatch_create_symtab(struct upatch_elf *); void upatch_write_output_elf(struct upatch_elf *, Elf *, char *, mode_t); -#endif /* __UPATCH_CREATE_H_ */ \ No newline at end of file +#endif /* __UPATCH_CREATE_H_ */ diff --git a/upatch-diff/elf-debug.c b/upatch-diff/elf-debug.c index 0490f862..677b8bce 100644 --- a/upatch-diff/elf-debug.c +++ b/upatch-diff/elf-debug.c @@ -36,12 +36,15 @@ void upatch_print_changes(struct upatch_elf *uelf) struct symbol *sym; list_for_each_entry(sym, &uelf->symbols, list) { - if (!sym->include || !sym->sec || sym->type != STT_FUNC || sym->parent) + if (!sym->include || !sym->sec || + sym->type != STT_FUNC || sym->parent) { continue; - if (sym->status == NEW) + } + if (sym->status == NEW) { log_normal("New function: %s\n", sym->name); - else if (sym->status == CHANGED) + } else if (sym->status == CHANGED) { log_normal("Changed function: %s\n", sym->name); + } } } @@ -53,26 +56,31 @@ void upatch_dump_kelf(struct upatch_elf *uelf) log_debug("\n=== Sections ===\n"); list_for_each_entry(sec, &uelf->sections, list) { - log_debug("%02d %s (%s)", sec->index, sec->name, status_str(sec->status)); + log_debug("%02d %s (%s)", + sec->index, sec->name, status_str(sec->status)); if (is_rela_section(sec)) { log_debug(", base-> %s\n", sec->base->name); - if (is_debug_section(sec) || is_note_section(sec)) + if (is_debug_section(sec) || is_note_section(sec)) { goto next; + } log_debug("rela section expansion\n"); list_for_each_entry(rela, &sec->relas, list) { - log_debug("sym %d, offset %ld, type %d, %s %s %ld \n", + log_debug("sym %d, offset %ld, type %d, %s %s %ld\n", rela->sym->index, rela->offset, rela->type, rela->sym->name, (rela->addend < 0) ? "-" : "+", labs(rela->addend)); } } else { - if (sec->sym) + if (sec->sym) { log_debug(", sym-> %s", sec->sym->name); - if (sec->secsym) + } + if (sec->secsym) { log_debug(", secsym-> %s", sec->secsym->name); - if (sec->rela) + } + if (sec->rela) { log_debug(", rela-> %s", sec->rela->name); + } } next: log_debug("\n"); @@ -83,14 +91,16 @@ next: log_debug("sym %02d, type %d, bind %d, ndx %02d, name %s (%s)", sym->index, sym->type, sym->bind, sym->sym.st_shndx, sym->name, status_str(sym->status)); - if (sym->sec && (sym->type == STT_FUNC || sym->type == STT_OBJECT)) + if (sym->sec && (sym->type == STT_FUNC || sym->type == STT_OBJECT)) { log_debug(" -> %s", sym->sec->name); + } log_debug("\n"); } } /* debuginfo releated */ -static inline bool skip_bytes(unsigned char **iter, unsigned char *end, unsigned int len) +static inline bool skip_bytes(unsigned char **iter, unsigned char *end, + unsigned int len) { if ((unsigned int)(end - *iter) < len) { *iter = end; @@ -104,26 +114,33 @@ void upatch_rebuild_eh_frame(struct section *sec) { void *eh_frame; unsigned long long frame_size; + struct rela *rela; - unsigned char *data, *data_end; - unsigned int hdr_length, hdr_id; + unsigned char *data; + unsigned char *data_end; + + unsigned int hdr_length; + unsigned int hdr_id; + unsigned long current_offset; unsigned int count = 0; /* sanity check */ - if (!is_eh_frame(sec) || is_rela_section(sec) || !sec->rela) + if (!is_eh_frame(sec) || is_rela_section(sec) || !sec->rela) { return; + } - list_for_each_entry(rela, &sec->rela->relas, list) - count ++; + list_for_each_entry(rela, &sec->rela->relas, list) { + count++; + } /* currently, only delete is possible */ if (sec->rela->sh.sh_entsize != 0 && - count == sec->rela->sh.sh_size / sec->rela->sh.sh_entsize) + count == sec->rela->sh.sh_size / sec->rela->sh.sh_entsize) { return; + } - log_debug("sync modification for eh_frame \n"); - + log_debug("sync modification for eh_frame\n"); data = sec->data->d_buf; data_end = sec->data->d_buf + sec->data->d_size; @@ -131,7 +148,7 @@ void upatch_rebuild_eh_frame(struct section *sec) frame_size = 0; eh_frame = calloc(1, sec->data->d_size); if (!eh_frame) { - ERROR("malloc eh_frame failed \n"); + ERROR("malloc eh_frame failed\n"); } /* 8 is the offset of PC begin */ @@ -139,27 +156,30 @@ void upatch_rebuild_eh_frame(struct section *sec) list_for_each_entry(rela, &sec->rela->relas, list) { unsigned long offset = rela->offset; bool found_rela = false; - log_debug("handle relocaton offset at 0x%lx \n", offset); + log_debug("handle relocaton offset at 0x%lx\n", offset); while (data != data_end) { void *__src = data; - log_debug("current handle offset is 0x%lx \n", current_offset); + log_debug("current handle offset is 0x%lx\n", current_offset); REQUIRE(skip_bytes(&data, data_end, 4), "no length to be read"); hdr_length = *(unsigned int *)(data - 4); - REQUIRE(hdr_length != 0xffffffff, "64 bit .eh_frame is not supported"); + REQUIRE(hdr_length != 0xffffffff, + "64 bit .eh_frame is not supported"); /* if it is 0, we reach the end. */ - if (hdr_length == 0) + if (hdr_length == 0) { break; + } REQUIRE(skip_bytes(&data, data_end, 4), "no length to be read"); hdr_id = *(unsigned int *)(data - 4); - REQUIRE(skip_bytes(&data, data_end, hdr_length - 4), "no length to be read"); - - if (current_offset == offset) + REQUIRE(skip_bytes(&data, data_end, hdr_length - 4), + "no length to be read"); + if (current_offset == offset) { found_rela = true; + } /* CIE or relocation releated FDE */ if (hdr_id == 0 || found_rela) { @@ -173,14 +193,14 @@ void upatch_rebuild_eh_frame(struct section *sec) frame_size += (hdr_length + 4); } else { - log_debug("remove FDE at 0x%lx \n", current_offset); + log_debug("remove FDE at 0x%lx\n", current_offset); } - /* hdr_length(value) + hdr_length(body) */ current_offset += (4 + hdr_length); - if (found_rela) + if (found_rela) { break; + } } } diff --git a/upatch-diff/elf-insn.c b/upatch-diff/elf-insn.c index 11380d07..8fcfc39d 100644 --- a/upatch-diff/elf-insn.c +++ b/upatch-diff/elf-insn.c @@ -30,24 +30,30 @@ void rela_insn(const struct section *sec, const struct rela *rela, struct insn *insn) { - unsigned long insn_addr, start, end, rela_addr; + unsigned long start; + unsigned long end; + + unsigned long rela_addr; + unsigned long insn_addr; start = (unsigned long)sec->data->d_buf; end = start + sec->sh.sh_size; - if (end <= start) + if (end <= start) { ERROR("bad section size"); + } rela_addr = start + rela->offset; for (insn_addr = start; insn_addr < end; insn_addr += insn->length) { insn_init(insn, (void *)insn_addr, 1); insn_get_length(insn); - if (!insn->length) + if (!insn->length) { ERROR("can't decode instruction in section %s at offset 0x%lx", sec->name, insn_addr); - if (rela_addr >= insn_addr && - rela_addr < insn_addr + insn->length) + } + if (rela_addr >= insn_addr && rela_addr < insn_addr + insn->length) { return; + } } ERROR("can't find instruction for rela at %s+0x%lx", @@ -56,33 +62,33 @@ void rela_insn(const struct section *sec, const struct rela *rela, struct insn * long rela_target_offset(struct upatch_elf *uelf, struct section *relasec, struct rela *rela) { - long add_off; struct section *sec = relasec->base; + long add_off; - switch(uelf->arch) { - case AARCH64: - add_off = 0; - break; - case X86_64: - if (!is_text_section(sec) || - rela->type == R_X86_64_64 || - rela->type == R_X86_64_32 || - rela->type == R_X86_64_32S) + switch (uelf->arch) { + case AARCH64: add_off = 0; - else if (rela->type == R_X86_64_PC32 || - rela->type == R_X86_64_PLT32) { - struct insn insn; - rela_insn(sec, rela, &insn); - add_off = (long)insn.next_byte - - (long)sec->data->d_buf - - (long)rela->offset; - } else { - ERROR("unable to handle rela type %d \n", rela->type); - } - break; - default: - ERROR("unsupported arch \n"); - break; + break; + case X86_64: + if (!is_text_section(sec) || + rela->type == R_X86_64_64 || + rela->type == R_X86_64_32 || + rela->type == R_X86_64_32S) { + add_off = 0; + } else if (rela->type == R_X86_64_PC32 || rela->type == R_X86_64_PLT32) { + struct insn insn; + rela_insn(sec, rela, &insn); + + add_off = (long)insn.next_byte - + (long)sec->data->d_buf - + (long)rela->offset; + } else { + ERROR("unable to handle rela type %d\n", rela->type); + } + break; + default: + ERROR("unsupported arch\n"); + break; } return rela->addend + add_off; @@ -92,15 +98,15 @@ unsigned int insn_length(struct upatch_elf *uelf, void *addr) { struct insn decoded_insn; - switch(uelf->arch) { - case AARCH64: - return ARM64_INSTR_LEN; - case X86_64: - insn_init(&decoded_insn, addr, 1); - insn_get_length(&decoded_insn); - return decoded_insn.length; - default: - ERROR("unsupported arch"); + switch (uelf->arch) { + case AARCH64: + return ARM64_INSTR_LEN; + case X86_64: + insn_init(&decoded_insn, addr, 1); + insn_get_length(&decoded_insn); + return decoded_insn.length; + default: + ERROR("unsupported arch"); } return 0; @@ -111,23 +117,23 @@ bool insn_is_load_immediate(struct upatch_elf *uelf, void *addr) { unsigned char *insn = addr; - switch(uelf->arch) { - case X86_64: - /* arg2: mov $imm, %esi */ - if (insn[0] == 0xbe) - return true; - - /* arg3: mov $imm, %edx */ - if (insn[0] == 0xba) - return true; - - /* 0x41 is the prefix extend - REX.B */ - if (insn[0] == 0x41 && insn[1] == 0xb8) - return true; - - break; - default: - ERROR("unsupported arch"); + switch (uelf->arch) { + case X86_64: + /* arg2: mov $imm, %esi */ + if (insn[0] == 0xbe) { + return true; + } + /* arg3: mov $imm, %edx */ + if (insn[0] == 0xba) { + return true; + } + /* 0x41 is the prefix extend - REX.B */ + if (insn[0] == 0x41 && insn[1] == 0xb8) { + return true; + } + break; + default: + ERROR("unsupported arch"); } return false; -} \ No newline at end of file +} diff --git a/upatch-diff/elf-resolve.c b/upatch-diff/elf-resolve.c index 0eb55cc2..67ab0692 100755 --- a/upatch-diff/elf-resolve.c +++ b/upatch-diff/elf-resolve.c @@ -34,11 +34,12 @@ void upatch_partly_resolve(struct upatch_elf *uelf, struct running_elf *relf) list_for_each_entry(sym, &uelf->symbols, list) { if (sym->sym.st_other & SYM_OTHER) { - if (!lookup_relf(relf, sym, &symbol)) + if (!lookup_relf(relf, sym, &symbol)) { continue; + } /* keep it undefined for link purpose */ sym->sym.st_value = symbol.symbol->addr; sym->sym.st_size = symbol.symbol->size; } } -} \ No newline at end of file +} diff --git a/upatch-diff/elf-resolve.h b/upatch-diff/elf-resolve.h index 9eccdfd6..05b4b356 100755 --- a/upatch-diff/elf-resolve.h +++ b/upatch-diff/elf-resolve.h @@ -25,4 +25,4 @@ void upatch_partly_resolve(struct upatch_elf *, struct running_elf *); -#endif /* __UPATCH_RESOLVE_H_ */ \ No newline at end of file +#endif /* __UPATCH_RESOLVE_H_ */ diff --git a/upatch-diff/insn/asm/inat-tables.h b/upatch-diff/insn/asm/inat-tables.h index 8419e2e4..331eb86a 100644 --- a/upatch-diff/insn/asm/inat-tables.h +++ b/upatch-diff/insn/asm/inat-tables.h @@ -11,922 +11,922 @@ /* Table: one byte opcode */ const insn_attr_t inat_primary_table[INAT_OPCODE_TABLE_SIZE] = { - [0x00] = INAT_MODRM, - [0x01] = INAT_MODRM, - [0x02] = INAT_MODRM, - [0x03] = INAT_MODRM, - [0x04] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x05] = INAT_MAKE_IMM(INAT_IMM_VWORD32), - [0x08] = INAT_MODRM, - [0x09] = INAT_MODRM, - [0x0a] = INAT_MODRM, - [0x0b] = INAT_MODRM, - [0x0c] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x0d] = INAT_MAKE_IMM(INAT_IMM_VWORD32), - [0x0f] = INAT_MAKE_ESCAPE(1), - [0x10] = INAT_MODRM, - [0x11] = INAT_MODRM, - [0x12] = INAT_MODRM, - [0x13] = INAT_MODRM, - [0x14] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x15] = INAT_MAKE_IMM(INAT_IMM_VWORD32), - [0x18] = INAT_MODRM, - [0x19] = INAT_MODRM, - [0x1a] = INAT_MODRM, - [0x1b] = INAT_MODRM, - [0x1c] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x1d] = INAT_MAKE_IMM(INAT_IMM_VWORD32), - [0x20] = INAT_MODRM, - [0x21] = INAT_MODRM, - [0x22] = INAT_MODRM, - [0x23] = INAT_MODRM, - [0x24] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x25] = INAT_MAKE_IMM(INAT_IMM_VWORD32), - [0x26] = INAT_MAKE_PREFIX(INAT_PFX_ES), - [0x28] = INAT_MODRM, - [0x29] = INAT_MODRM, - [0x2a] = INAT_MODRM, - [0x2b] = INAT_MODRM, - [0x2c] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x2d] = INAT_MAKE_IMM(INAT_IMM_VWORD32), - [0x2e] = INAT_MAKE_PREFIX(INAT_PFX_CS), - [0x30] = INAT_MODRM, - [0x31] = INAT_MODRM, - [0x32] = INAT_MODRM, - [0x33] = INAT_MODRM, - [0x34] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x35] = INAT_MAKE_IMM(INAT_IMM_VWORD32), - [0x36] = INAT_MAKE_PREFIX(INAT_PFX_SS), - [0x38] = INAT_MODRM, - [0x39] = INAT_MODRM, - [0x3a] = INAT_MODRM, - [0x3b] = INAT_MODRM, - [0x3c] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x3d] = INAT_MAKE_IMM(INAT_IMM_VWORD32), - [0x3e] = INAT_MAKE_PREFIX(INAT_PFX_DS), - [0x40] = INAT_MAKE_PREFIX(INAT_PFX_REX), - [0x41] = INAT_MAKE_PREFIX(INAT_PFX_REX), - [0x42] = INAT_MAKE_PREFIX(INAT_PFX_REX), - [0x43] = INAT_MAKE_PREFIX(INAT_PFX_REX), - [0x44] = INAT_MAKE_PREFIX(INAT_PFX_REX), - [0x45] = INAT_MAKE_PREFIX(INAT_PFX_REX), - [0x46] = INAT_MAKE_PREFIX(INAT_PFX_REX), - [0x47] = INAT_MAKE_PREFIX(INAT_PFX_REX), - [0x48] = INAT_MAKE_PREFIX(INAT_PFX_REX), - [0x49] = INAT_MAKE_PREFIX(INAT_PFX_REX), - [0x4a] = INAT_MAKE_PREFIX(INAT_PFX_REX), - [0x4b] = INAT_MAKE_PREFIX(INAT_PFX_REX), - [0x4c] = INAT_MAKE_PREFIX(INAT_PFX_REX), - [0x4d] = INAT_MAKE_PREFIX(INAT_PFX_REX), - [0x4e] = INAT_MAKE_PREFIX(INAT_PFX_REX), - [0x4f] = INAT_MAKE_PREFIX(INAT_PFX_REX), - [0x50] = INAT_FORCE64, - [0x51] = INAT_FORCE64, - [0x52] = INAT_FORCE64, - [0x53] = INAT_FORCE64, - [0x54] = INAT_FORCE64, - [0x55] = INAT_FORCE64, - [0x56] = INAT_FORCE64, - [0x57] = INAT_FORCE64, - [0x58] = INAT_FORCE64, - [0x59] = INAT_FORCE64, - [0x5a] = INAT_FORCE64, - [0x5b] = INAT_FORCE64, - [0x5c] = INAT_FORCE64, - [0x5d] = INAT_FORCE64, - [0x5e] = INAT_FORCE64, - [0x5f] = INAT_FORCE64, - [0x62] = INAT_MODRM, - [0x63] = INAT_MODRM | INAT_MODRM, - [0x64] = INAT_MAKE_PREFIX(INAT_PFX_FS), - [0x65] = INAT_MAKE_PREFIX(INAT_PFX_GS), - [0x66] = INAT_MAKE_PREFIX(INAT_PFX_OPNDSZ), - [0x67] = INAT_MAKE_PREFIX(INAT_PFX_ADDRSZ), - [0x68] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, - [0x69] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_MODRM, - [0x6a] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_FORCE64, - [0x6b] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM, - [0x70] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x71] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x72] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x73] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x74] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x75] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x76] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x77] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x78] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x79] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x7a] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x7b] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x7c] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x7d] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x7e] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x7f] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0x80] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_MAKE_GROUP(1), - [0x81] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_MODRM | INAT_MAKE_GROUP(1), - [0x82] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_MAKE_GROUP(1), - [0x83] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_MAKE_GROUP(1), - [0x84] = INAT_MODRM, - [0x85] = INAT_MODRM, - [0x86] = INAT_MODRM, - [0x87] = INAT_MODRM, - [0x88] = INAT_MODRM, - [0x89] = INAT_MODRM, - [0x8a] = INAT_MODRM, - [0x8b] = INAT_MODRM, - [0x8c] = INAT_MODRM, - [0x8d] = INAT_MODRM, - [0x8e] = INAT_MODRM, - [0x8f] = INAT_MAKE_GROUP(2) | INAT_MODRM | INAT_FORCE64, - [0x9a] = INAT_MAKE_IMM(INAT_IMM_PTR), - [0x9c] = INAT_FORCE64, - [0x9d] = INAT_FORCE64, - [0xa0] = INAT_MOFFSET, - [0xa1] = INAT_MOFFSET, - [0xa2] = INAT_MOFFSET, - [0xa3] = INAT_MOFFSET, - [0xa8] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0xa9] = INAT_MAKE_IMM(INAT_IMM_VWORD32), - [0xb0] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0xb1] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0xb2] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0xb3] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0xb4] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0xb5] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0xb6] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0xb7] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0xb8] = INAT_MAKE_IMM(INAT_IMM_VWORD), - [0xb9] = INAT_MAKE_IMM(INAT_IMM_VWORD), - [0xba] = INAT_MAKE_IMM(INAT_IMM_VWORD), - [0xbb] = INAT_MAKE_IMM(INAT_IMM_VWORD), - [0xbc] = INAT_MAKE_IMM(INAT_IMM_VWORD), - [0xbd] = INAT_MAKE_IMM(INAT_IMM_VWORD), - [0xbe] = INAT_MAKE_IMM(INAT_IMM_VWORD), - [0xbf] = INAT_MAKE_IMM(INAT_IMM_VWORD), - [0xc0] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_MAKE_GROUP(3), - [0xc1] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_MAKE_GROUP(3), - [0xc2] = INAT_MAKE_IMM(INAT_IMM_WORD) | INAT_FORCE64, - [0xc4] = INAT_MODRM | INAT_MAKE_PREFIX(INAT_PFX_VEX3), - [0xc5] = INAT_MODRM | INAT_MAKE_PREFIX(INAT_PFX_VEX2), - [0xc6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_MAKE_GROUP(4), - [0xc7] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_MODRM | INAT_MAKE_GROUP(5), - [0xc8] = INAT_MAKE_IMM(INAT_IMM_WORD) | INAT_SCNDIMM, - [0xc9] = INAT_FORCE64, - [0xca] = INAT_MAKE_IMM(INAT_IMM_WORD), - [0xcd] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0xd0] = INAT_MODRM | INAT_MAKE_GROUP(3), - [0xd1] = INAT_MODRM | INAT_MAKE_GROUP(3), - [0xd2] = INAT_MODRM | INAT_MAKE_GROUP(3), - [0xd3] = INAT_MODRM | INAT_MAKE_GROUP(3), - [0xd4] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0xd5] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0xd8] = INAT_MODRM, - [0xd9] = INAT_MODRM, - [0xda] = INAT_MODRM, - [0xdb] = INAT_MODRM, - [0xdc] = INAT_MODRM, - [0xdd] = INAT_MODRM, - [0xde] = INAT_MODRM, - [0xdf] = INAT_MODRM, - [0xe0] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_FORCE64, - [0xe1] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_FORCE64, - [0xe2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_FORCE64, - [0xe3] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_FORCE64, - [0xe4] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0xe5] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0xe6] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0xe7] = INAT_MAKE_IMM(INAT_IMM_BYTE), - [0xe8] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, - [0xe9] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, - [0xea] = INAT_MAKE_IMM(INAT_IMM_PTR), - [0xeb] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_FORCE64, - [0xf0] = INAT_MAKE_PREFIX(INAT_PFX_LOCK), - [0xf2] = INAT_MAKE_PREFIX(INAT_PFX_REPNE) | INAT_MAKE_PREFIX(INAT_PFX_REPNE), - [0xf3] = INAT_MAKE_PREFIX(INAT_PFX_REPE) | INAT_MAKE_PREFIX(INAT_PFX_REPE), - [0xf6] = INAT_MODRM | INAT_MAKE_GROUP(6), - [0xf7] = INAT_MODRM | INAT_MAKE_GROUP(7), - [0xfe] = INAT_MAKE_GROUP(8), - [0xff] = INAT_MAKE_GROUP(9), + [0x00] = INAT_MODRM, + [0x01] = INAT_MODRM, + [0x02] = INAT_MODRM, + [0x03] = INAT_MODRM, + [0x04] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x05] = INAT_MAKE_IMM(INAT_IMM_VWORD32), + [0x08] = INAT_MODRM, + [0x09] = INAT_MODRM, + [0x0a] = INAT_MODRM, + [0x0b] = INAT_MODRM, + [0x0c] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x0d] = INAT_MAKE_IMM(INAT_IMM_VWORD32), + [0x0f] = INAT_MAKE_ESCAPE(1), + [0x10] = INAT_MODRM, + [0x11] = INAT_MODRM, + [0x12] = INAT_MODRM, + [0x13] = INAT_MODRM, + [0x14] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x15] = INAT_MAKE_IMM(INAT_IMM_VWORD32), + [0x18] = INAT_MODRM, + [0x19] = INAT_MODRM, + [0x1a] = INAT_MODRM, + [0x1b] = INAT_MODRM, + [0x1c] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x1d] = INAT_MAKE_IMM(INAT_IMM_VWORD32), + [0x20] = INAT_MODRM, + [0x21] = INAT_MODRM, + [0x22] = INAT_MODRM, + [0x23] = INAT_MODRM, + [0x24] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x25] = INAT_MAKE_IMM(INAT_IMM_VWORD32), + [0x26] = INAT_MAKE_PREFIX(INAT_PFX_ES), + [0x28] = INAT_MODRM, + [0x29] = INAT_MODRM, + [0x2a] = INAT_MODRM, + [0x2b] = INAT_MODRM, + [0x2c] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x2d] = INAT_MAKE_IMM(INAT_IMM_VWORD32), + [0x2e] = INAT_MAKE_PREFIX(INAT_PFX_CS), + [0x30] = INAT_MODRM, + [0x31] = INAT_MODRM, + [0x32] = INAT_MODRM, + [0x33] = INAT_MODRM, + [0x34] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x35] = INAT_MAKE_IMM(INAT_IMM_VWORD32), + [0x36] = INAT_MAKE_PREFIX(INAT_PFX_SS), + [0x38] = INAT_MODRM, + [0x39] = INAT_MODRM, + [0x3a] = INAT_MODRM, + [0x3b] = INAT_MODRM, + [0x3c] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x3d] = INAT_MAKE_IMM(INAT_IMM_VWORD32), + [0x3e] = INAT_MAKE_PREFIX(INAT_PFX_DS), + [0x40] = INAT_MAKE_PREFIX(INAT_PFX_REX), + [0x41] = INAT_MAKE_PREFIX(INAT_PFX_REX), + [0x42] = INAT_MAKE_PREFIX(INAT_PFX_REX), + [0x43] = INAT_MAKE_PREFIX(INAT_PFX_REX), + [0x44] = INAT_MAKE_PREFIX(INAT_PFX_REX), + [0x45] = INAT_MAKE_PREFIX(INAT_PFX_REX), + [0x46] = INAT_MAKE_PREFIX(INAT_PFX_REX), + [0x47] = INAT_MAKE_PREFIX(INAT_PFX_REX), + [0x48] = INAT_MAKE_PREFIX(INAT_PFX_REX), + [0x49] = INAT_MAKE_PREFIX(INAT_PFX_REX), + [0x4a] = INAT_MAKE_PREFIX(INAT_PFX_REX), + [0x4b] = INAT_MAKE_PREFIX(INAT_PFX_REX), + [0x4c] = INAT_MAKE_PREFIX(INAT_PFX_REX), + [0x4d] = INAT_MAKE_PREFIX(INAT_PFX_REX), + [0x4e] = INAT_MAKE_PREFIX(INAT_PFX_REX), + [0x4f] = INAT_MAKE_PREFIX(INAT_PFX_REX), + [0x50] = INAT_FORCE64, + [0x51] = INAT_FORCE64, + [0x52] = INAT_FORCE64, + [0x53] = INAT_FORCE64, + [0x54] = INAT_FORCE64, + [0x55] = INAT_FORCE64, + [0x56] = INAT_FORCE64, + [0x57] = INAT_FORCE64, + [0x58] = INAT_FORCE64, + [0x59] = INAT_FORCE64, + [0x5a] = INAT_FORCE64, + [0x5b] = INAT_FORCE64, + [0x5c] = INAT_FORCE64, + [0x5d] = INAT_FORCE64, + [0x5e] = INAT_FORCE64, + [0x5f] = INAT_FORCE64, + [0x62] = INAT_MODRM, + [0x63] = INAT_MODRM | INAT_MODRM, + [0x64] = INAT_MAKE_PREFIX(INAT_PFX_FS), + [0x65] = INAT_MAKE_PREFIX(INAT_PFX_GS), + [0x66] = INAT_MAKE_PREFIX(INAT_PFX_OPNDSZ), + [0x67] = INAT_MAKE_PREFIX(INAT_PFX_ADDRSZ), + [0x68] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, + [0x69] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_MODRM, + [0x6a] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_FORCE64, + [0x6b] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM, + [0x70] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x71] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x72] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x73] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x74] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x75] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x76] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x77] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x78] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x79] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x7a] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x7b] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x7c] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x7d] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x7e] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x7f] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x80] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_MAKE_GROUP(1), + [0x81] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_MODRM | INAT_MAKE_GROUP(1), + [0x82] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_MAKE_GROUP(1), + [0x83] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_MAKE_GROUP(1), + [0x84] = INAT_MODRM, + [0x85] = INAT_MODRM, + [0x86] = INAT_MODRM, + [0x87] = INAT_MODRM, + [0x88] = INAT_MODRM, + [0x89] = INAT_MODRM, + [0x8a] = INAT_MODRM, + [0x8b] = INAT_MODRM, + [0x8c] = INAT_MODRM, + [0x8d] = INAT_MODRM, + [0x8e] = INAT_MODRM, + [0x8f] = INAT_MAKE_GROUP(2) | INAT_MODRM | INAT_FORCE64, + [0x9a] = INAT_MAKE_IMM(INAT_IMM_PTR), + [0x9c] = INAT_FORCE64, + [0x9d] = INAT_FORCE64, + [0xa0] = INAT_MOFFSET, + [0xa1] = INAT_MOFFSET, + [0xa2] = INAT_MOFFSET, + [0xa3] = INAT_MOFFSET, + [0xa8] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0xa9] = INAT_MAKE_IMM(INAT_IMM_VWORD32), + [0xb0] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0xb1] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0xb2] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0xb3] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0xb4] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0xb5] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0xb6] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0xb7] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0xb8] = INAT_MAKE_IMM(INAT_IMM_VWORD), + [0xb9] = INAT_MAKE_IMM(INAT_IMM_VWORD), + [0xba] = INAT_MAKE_IMM(INAT_IMM_VWORD), + [0xbb] = INAT_MAKE_IMM(INAT_IMM_VWORD), + [0xbc] = INAT_MAKE_IMM(INAT_IMM_VWORD), + [0xbd] = INAT_MAKE_IMM(INAT_IMM_VWORD), + [0xbe] = INAT_MAKE_IMM(INAT_IMM_VWORD), + [0xbf] = INAT_MAKE_IMM(INAT_IMM_VWORD), + [0xc0] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_MAKE_GROUP(3), + [0xc1] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_MAKE_GROUP(3), + [0xc2] = INAT_MAKE_IMM(INAT_IMM_WORD) | INAT_FORCE64, + [0xc4] = INAT_MODRM | INAT_MAKE_PREFIX(INAT_PFX_VEX3), + [0xc5] = INAT_MODRM | INAT_MAKE_PREFIX(INAT_PFX_VEX2), + [0xc6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_MAKE_GROUP(4), + [0xc7] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_MODRM | INAT_MAKE_GROUP(5), + [0xc8] = INAT_MAKE_IMM(INAT_IMM_WORD) | INAT_SCNDIMM, + [0xc9] = INAT_FORCE64, + [0xca] = INAT_MAKE_IMM(INAT_IMM_WORD), + [0xcd] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0xd0] = INAT_MODRM | INAT_MAKE_GROUP(3), + [0xd1] = INAT_MODRM | INAT_MAKE_GROUP(3), + [0xd2] = INAT_MODRM | INAT_MAKE_GROUP(3), + [0xd3] = INAT_MODRM | INAT_MAKE_GROUP(3), + [0xd4] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0xd5] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0xd8] = INAT_MODRM, + [0xd9] = INAT_MODRM, + [0xda] = INAT_MODRM, + [0xdb] = INAT_MODRM, + [0xdc] = INAT_MODRM, + [0xdd] = INAT_MODRM, + [0xde] = INAT_MODRM, + [0xdf] = INAT_MODRM, + [0xe0] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_FORCE64, + [0xe1] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_FORCE64, + [0xe2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_FORCE64, + [0xe3] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_FORCE64, + [0xe4] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0xe5] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0xe6] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0xe7] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0xe8] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, + [0xe9] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, + [0xea] = INAT_MAKE_IMM(INAT_IMM_PTR), + [0xeb] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_FORCE64, + [0xf0] = INAT_MAKE_PREFIX(INAT_PFX_LOCK), + [0xf2] = INAT_MAKE_PREFIX(INAT_PFX_REPNE) | INAT_MAKE_PREFIX(INAT_PFX_REPNE), + [0xf3] = INAT_MAKE_PREFIX(INAT_PFX_REPE) | INAT_MAKE_PREFIX(INAT_PFX_REPE), + [0xf6] = INAT_MODRM | INAT_MAKE_GROUP(6), + [0xf7] = INAT_MODRM | INAT_MAKE_GROUP(7), + [0xfe] = INAT_MAKE_GROUP(8), + [0xff] = INAT_MAKE_GROUP(9), }; /* Table: 2-byte opcode (0x0f) */ const insn_attr_t inat_escape_table_1[INAT_OPCODE_TABLE_SIZE] = { - [0x00] = INAT_MAKE_GROUP(10), - [0x01] = INAT_MAKE_GROUP(11), - [0x02] = INAT_MODRM, - [0x03] = INAT_MODRM, - [0x0d] = INAT_MAKE_GROUP(12), - [0x0f] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM, - [0x10] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x11] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x12] = INAT_MODRM | INAT_VEXOK | INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x13] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x14] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x15] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x16] = INAT_MODRM | INAT_VEXOK | INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x17] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x18] = INAT_MAKE_GROUP(13), - [0x1a] = INAT_MODRM | INAT_MODRM | INAT_MODRM | INAT_MODRM, - [0x1b] = INAT_MODRM | INAT_MODRM | INAT_MODRM | INAT_MODRM, - [0x1f] = INAT_MODRM, - [0x20] = INAT_MODRM, - [0x21] = INAT_MODRM, - [0x22] = INAT_MODRM, - [0x23] = INAT_MODRM, - [0x28] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x29] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x2a] = INAT_MODRM | INAT_VARIANT, - [0x2b] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x2c] = INAT_MODRM | INAT_VARIANT, - [0x2d] = INAT_MODRM | INAT_VARIANT, - [0x2e] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x2f] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x38] = INAT_MAKE_ESCAPE(2), - [0x3a] = INAT_MAKE_ESCAPE(3), - [0x40] = INAT_MODRM, - [0x41] = INAT_MODRM, - [0x42] = INAT_MODRM, - [0x43] = INAT_MODRM, - [0x44] = INAT_MODRM, - [0x45] = INAT_MODRM, - [0x46] = INAT_MODRM, - [0x47] = INAT_MODRM, - [0x48] = INAT_MODRM, - [0x49] = INAT_MODRM, - [0x4a] = INAT_MODRM, - [0x4b] = INAT_MODRM, - [0x4c] = INAT_MODRM, - [0x4d] = INAT_MODRM, - [0x4e] = INAT_MODRM, - [0x4f] = INAT_MODRM, - [0x50] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x51] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x52] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x53] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x54] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x55] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x56] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x57] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x58] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x59] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x5a] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x5b] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x5c] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x5d] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x5e] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x5f] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x60] = INAT_MODRM | INAT_VARIANT, - [0x61] = INAT_MODRM | INAT_VARIANT, - [0x62] = INAT_MODRM | INAT_VARIANT, - [0x63] = INAT_MODRM | INAT_VARIANT, - [0x64] = INAT_MODRM | INAT_VARIANT, - [0x65] = INAT_MODRM | INAT_VARIANT, - [0x66] = INAT_MODRM | INAT_VARIANT, - [0x67] = INAT_MODRM | INAT_VARIANT, - [0x68] = INAT_MODRM | INAT_VARIANT, - [0x69] = INAT_MODRM | INAT_VARIANT, - [0x6a] = INAT_MODRM | INAT_VARIANT, - [0x6b] = INAT_MODRM | INAT_VARIANT, - [0x6c] = INAT_VARIANT, - [0x6d] = INAT_VARIANT, - [0x6e] = INAT_MODRM | INAT_VARIANT, - [0x6f] = INAT_MODRM | INAT_VARIANT, - [0x70] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, - [0x71] = INAT_MAKE_GROUP(14), - [0x72] = INAT_MAKE_GROUP(15), - [0x73] = INAT_MAKE_GROUP(16), - [0x74] = INAT_MODRM | INAT_VARIANT, - [0x75] = INAT_MODRM | INAT_VARIANT, - [0x76] = INAT_MODRM | INAT_VARIANT, - [0x77] = INAT_VEXOK | INAT_VEXOK, - [0x78] = INAT_MODRM, - [0x79] = INAT_MODRM, - [0x7c] = INAT_VARIANT, - [0x7d] = INAT_VARIANT, - [0x7e] = INAT_MODRM | INAT_VARIANT, - [0x7f] = INAT_MODRM | INAT_VARIANT, - [0x80] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, - [0x81] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, - [0x82] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, - [0x83] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, - [0x84] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, - [0x85] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, - [0x86] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, - [0x87] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, - [0x88] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, - [0x89] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, - [0x8a] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, - [0x8b] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, - [0x8c] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, - [0x8d] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, - [0x8e] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, - [0x8f] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, - [0x90] = INAT_MODRM, - [0x91] = INAT_MODRM, - [0x92] = INAT_MODRM, - [0x93] = INAT_MODRM, - [0x94] = INAT_MODRM, - [0x95] = INAT_MODRM, - [0x96] = INAT_MODRM, - [0x97] = INAT_MODRM, - [0x98] = INAT_MODRM, - [0x99] = INAT_MODRM, - [0x9a] = INAT_MODRM, - [0x9b] = INAT_MODRM, - [0x9c] = INAT_MODRM, - [0x9d] = INAT_MODRM, - [0x9e] = INAT_MODRM, - [0x9f] = INAT_MODRM, - [0xa0] = INAT_FORCE64, - [0xa1] = INAT_FORCE64, - [0xa3] = INAT_MODRM, - [0xa4] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM, - [0xa5] = INAT_MODRM, - [0xa6] = INAT_MAKE_GROUP(17), - [0xa7] = INAT_MAKE_GROUP(18), - [0xa8] = INAT_FORCE64, - [0xa9] = INAT_FORCE64, - [0xab] = INAT_MODRM, - [0xac] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM, - [0xad] = INAT_MODRM, - [0xae] = INAT_MAKE_GROUP(19), - [0xaf] = INAT_MODRM, - [0xb0] = INAT_MODRM, - [0xb1] = INAT_MODRM, - [0xb2] = INAT_MODRM, - [0xb3] = INAT_MODRM, - [0xb4] = INAT_MODRM, - [0xb5] = INAT_MODRM, - [0xb6] = INAT_MODRM, - [0xb7] = INAT_MODRM, - [0xb8] = INAT_VARIANT, - [0xb9] = INAT_MAKE_GROUP(20), - [0xba] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_MAKE_GROUP(21), - [0xbb] = INAT_MODRM, - [0xbc] = INAT_MODRM | INAT_VARIANT, - [0xbd] = INAT_MODRM | INAT_VARIANT, - [0xbe] = INAT_MODRM, - [0xbf] = INAT_MODRM, - [0xc0] = INAT_MODRM, - [0xc1] = INAT_MODRM, - [0xc2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0xc3] = INAT_MODRM, - [0xc4] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, - [0xc5] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, - [0xc6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0xc7] = INAT_MAKE_GROUP(22), - [0xd0] = INAT_VARIANT, - [0xd1] = INAT_MODRM | INAT_VARIANT, - [0xd2] = INAT_MODRM | INAT_VARIANT, - [0xd3] = INAT_MODRM | INAT_VARIANT, - [0xd4] = INAT_MODRM | INAT_VARIANT, - [0xd5] = INAT_MODRM | INAT_VARIANT, - [0xd6] = INAT_VARIANT, - [0xd7] = INAT_MODRM | INAT_VARIANT, - [0xd8] = INAT_MODRM | INAT_VARIANT, - [0xd9] = INAT_MODRM | INAT_VARIANT, - [0xda] = INAT_MODRM | INAT_VARIANT, - [0xdb] = INAT_MODRM | INAT_VARIANT, - [0xdc] = INAT_MODRM | INAT_VARIANT, - [0xdd] = INAT_MODRM | INAT_VARIANT, - [0xde] = INAT_MODRM | INAT_VARIANT, - [0xdf] = INAT_MODRM | INAT_VARIANT, - [0xe0] = INAT_MODRM | INAT_VARIANT, - [0xe1] = INAT_MODRM | INAT_VARIANT, - [0xe2] = INAT_MODRM | INAT_VARIANT, - [0xe3] = INAT_MODRM | INAT_VARIANT, - [0xe4] = INAT_MODRM | INAT_VARIANT, - [0xe5] = INAT_MODRM | INAT_VARIANT, - [0xe6] = INAT_VARIANT, - [0xe7] = INAT_MODRM | INAT_VARIANT, - [0xe8] = INAT_MODRM | INAT_VARIANT, - [0xe9] = INAT_MODRM | INAT_VARIANT, - [0xea] = INAT_MODRM | INAT_VARIANT, - [0xeb] = INAT_MODRM | INAT_VARIANT, - [0xec] = INAT_MODRM | INAT_VARIANT, - [0xed] = INAT_MODRM | INAT_VARIANT, - [0xee] = INAT_MODRM | INAT_VARIANT, - [0xef] = INAT_MODRM | INAT_VARIANT, - [0xf0] = INAT_VARIANT, - [0xf1] = INAT_MODRM | INAT_VARIANT, - [0xf2] = INAT_MODRM | INAT_VARIANT, - [0xf3] = INAT_MODRM | INAT_VARIANT, - [0xf4] = INAT_MODRM | INAT_VARIANT, - [0xf5] = INAT_MODRM | INAT_VARIANT, - [0xf6] = INAT_MODRM | INAT_VARIANT, - [0xf7] = INAT_MODRM | INAT_VARIANT, - [0xf8] = INAT_MODRM | INAT_VARIANT, - [0xf9] = INAT_MODRM | INAT_VARIANT, - [0xfa] = INAT_MODRM | INAT_VARIANT, - [0xfb] = INAT_MODRM | INAT_VARIANT, - [0xfc] = INAT_MODRM | INAT_VARIANT, - [0xfd] = INAT_MODRM | INAT_VARIANT, - [0xfe] = INAT_MODRM | INAT_VARIANT, + [0x00] = INAT_MAKE_GROUP(10), + [0x01] = INAT_MAKE_GROUP(11), + [0x02] = INAT_MODRM, + [0x03] = INAT_MODRM, + [0x0d] = INAT_MAKE_GROUP(12), + [0x0f] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM, + [0x10] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x11] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x12] = INAT_MODRM | INAT_VEXOK | INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x13] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x14] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x15] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x16] = INAT_MODRM | INAT_VEXOK | INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x17] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x18] = INAT_MAKE_GROUP(13), + [0x1a] = INAT_MODRM | INAT_MODRM | INAT_MODRM | INAT_MODRM, + [0x1b] = INAT_MODRM | INAT_MODRM | INAT_MODRM | INAT_MODRM, + [0x1f] = INAT_MODRM, + [0x20] = INAT_MODRM, + [0x21] = INAT_MODRM, + [0x22] = INAT_MODRM, + [0x23] = INAT_MODRM, + [0x28] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x29] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x2a] = INAT_MODRM | INAT_VARIANT, + [0x2b] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x2c] = INAT_MODRM | INAT_VARIANT, + [0x2d] = INAT_MODRM | INAT_VARIANT, + [0x2e] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x2f] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x38] = INAT_MAKE_ESCAPE(2), + [0x3a] = INAT_MAKE_ESCAPE(3), + [0x40] = INAT_MODRM, + [0x41] = INAT_MODRM, + [0x42] = INAT_MODRM, + [0x43] = INAT_MODRM, + [0x44] = INAT_MODRM, + [0x45] = INAT_MODRM, + [0x46] = INAT_MODRM, + [0x47] = INAT_MODRM, + [0x48] = INAT_MODRM, + [0x49] = INAT_MODRM, + [0x4a] = INAT_MODRM, + [0x4b] = INAT_MODRM, + [0x4c] = INAT_MODRM, + [0x4d] = INAT_MODRM, + [0x4e] = INAT_MODRM, + [0x4f] = INAT_MODRM, + [0x50] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x51] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x52] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x53] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x54] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x55] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x56] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x57] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x58] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x59] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x5a] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x5b] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x5c] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x5d] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x5e] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x5f] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x60] = INAT_MODRM | INAT_VARIANT, + [0x61] = INAT_MODRM | INAT_VARIANT, + [0x62] = INAT_MODRM | INAT_VARIANT, + [0x63] = INAT_MODRM | INAT_VARIANT, + [0x64] = INAT_MODRM | INAT_VARIANT, + [0x65] = INAT_MODRM | INAT_VARIANT, + [0x66] = INAT_MODRM | INAT_VARIANT, + [0x67] = INAT_MODRM | INAT_VARIANT, + [0x68] = INAT_MODRM | INAT_VARIANT, + [0x69] = INAT_MODRM | INAT_VARIANT, + [0x6a] = INAT_MODRM | INAT_VARIANT, + [0x6b] = INAT_MODRM | INAT_VARIANT, + [0x6c] = INAT_VARIANT, + [0x6d] = INAT_VARIANT, + [0x6e] = INAT_MODRM | INAT_VARIANT, + [0x6f] = INAT_MODRM | INAT_VARIANT, + [0x70] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, + [0x71] = INAT_MAKE_GROUP(14), + [0x72] = INAT_MAKE_GROUP(15), + [0x73] = INAT_MAKE_GROUP(16), + [0x74] = INAT_MODRM | INAT_VARIANT, + [0x75] = INAT_MODRM | INAT_VARIANT, + [0x76] = INAT_MODRM | INAT_VARIANT, + [0x77] = INAT_VEXOK | INAT_VEXOK, + [0x78] = INAT_MODRM, + [0x79] = INAT_MODRM, + [0x7c] = INAT_VARIANT, + [0x7d] = INAT_VARIANT, + [0x7e] = INAT_MODRM | INAT_VARIANT, + [0x7f] = INAT_MODRM | INAT_VARIANT, + [0x80] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, + [0x81] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, + [0x82] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, + [0x83] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, + [0x84] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, + [0x85] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, + [0x86] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, + [0x87] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, + [0x88] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, + [0x89] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, + [0x8a] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, + [0x8b] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, + [0x8c] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, + [0x8d] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, + [0x8e] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, + [0x8f] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_FORCE64, + [0x90] = INAT_MODRM, + [0x91] = INAT_MODRM, + [0x92] = INAT_MODRM, + [0x93] = INAT_MODRM, + [0x94] = INAT_MODRM, + [0x95] = INAT_MODRM, + [0x96] = INAT_MODRM, + [0x97] = INAT_MODRM, + [0x98] = INAT_MODRM, + [0x99] = INAT_MODRM, + [0x9a] = INAT_MODRM, + [0x9b] = INAT_MODRM, + [0x9c] = INAT_MODRM, + [0x9d] = INAT_MODRM, + [0x9e] = INAT_MODRM, + [0x9f] = INAT_MODRM, + [0xa0] = INAT_FORCE64, + [0xa1] = INAT_FORCE64, + [0xa3] = INAT_MODRM, + [0xa4] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM, + [0xa5] = INAT_MODRM, + [0xa6] = INAT_MAKE_GROUP(17), + [0xa7] = INAT_MAKE_GROUP(18), + [0xa8] = INAT_FORCE64, + [0xa9] = INAT_FORCE64, + [0xab] = INAT_MODRM, + [0xac] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM, + [0xad] = INAT_MODRM, + [0xae] = INAT_MAKE_GROUP(19), + [0xaf] = INAT_MODRM, + [0xb0] = INAT_MODRM, + [0xb1] = INAT_MODRM, + [0xb2] = INAT_MODRM, + [0xb3] = INAT_MODRM, + [0xb4] = INAT_MODRM, + [0xb5] = INAT_MODRM, + [0xb6] = INAT_MODRM, + [0xb7] = INAT_MODRM, + [0xb8] = INAT_VARIANT, + [0xb9] = INAT_MAKE_GROUP(20), + [0xba] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_MAKE_GROUP(21), + [0xbb] = INAT_MODRM, + [0xbc] = INAT_MODRM | INAT_VARIANT, + [0xbd] = INAT_MODRM | INAT_VARIANT, + [0xbe] = INAT_MODRM, + [0xbf] = INAT_MODRM, + [0xc0] = INAT_MODRM, + [0xc1] = INAT_MODRM, + [0xc2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0xc3] = INAT_MODRM, + [0xc4] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, + [0xc5] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, + [0xc6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0xc7] = INAT_MAKE_GROUP(22), + [0xd0] = INAT_VARIANT, + [0xd1] = INAT_MODRM | INAT_VARIANT, + [0xd2] = INAT_MODRM | INAT_VARIANT, + [0xd3] = INAT_MODRM | INAT_VARIANT, + [0xd4] = INAT_MODRM | INAT_VARIANT, + [0xd5] = INAT_MODRM | INAT_VARIANT, + [0xd6] = INAT_VARIANT, + [0xd7] = INAT_MODRM | INAT_VARIANT, + [0xd8] = INAT_MODRM | INAT_VARIANT, + [0xd9] = INAT_MODRM | INAT_VARIANT, + [0xda] = INAT_MODRM | INAT_VARIANT, + [0xdb] = INAT_MODRM | INAT_VARIANT, + [0xdc] = INAT_MODRM | INAT_VARIANT, + [0xdd] = INAT_MODRM | INAT_VARIANT, + [0xde] = INAT_MODRM | INAT_VARIANT, + [0xdf] = INAT_MODRM | INAT_VARIANT, + [0xe0] = INAT_MODRM | INAT_VARIANT, + [0xe1] = INAT_MODRM | INAT_VARIANT, + [0xe2] = INAT_MODRM | INAT_VARIANT, + [0xe3] = INAT_MODRM | INAT_VARIANT, + [0xe4] = INAT_MODRM | INAT_VARIANT, + [0xe5] = INAT_MODRM | INAT_VARIANT, + [0xe6] = INAT_VARIANT, + [0xe7] = INAT_MODRM | INAT_VARIANT, + [0xe8] = INAT_MODRM | INAT_VARIANT, + [0xe9] = INAT_MODRM | INAT_VARIANT, + [0xea] = INAT_MODRM | INAT_VARIANT, + [0xeb] = INAT_MODRM | INAT_VARIANT, + [0xec] = INAT_MODRM | INAT_VARIANT, + [0xed] = INAT_MODRM | INAT_VARIANT, + [0xee] = INAT_MODRM | INAT_VARIANT, + [0xef] = INAT_MODRM | INAT_VARIANT, + [0xf0] = INAT_VARIANT, + [0xf1] = INAT_MODRM | INAT_VARIANT, + [0xf2] = INAT_MODRM | INAT_VARIANT, + [0xf3] = INAT_MODRM | INAT_VARIANT, + [0xf4] = INAT_MODRM | INAT_VARIANT, + [0xf5] = INAT_MODRM | INAT_VARIANT, + [0xf6] = INAT_MODRM | INAT_VARIANT, + [0xf7] = INAT_MODRM | INAT_VARIANT, + [0xf8] = INAT_MODRM | INAT_VARIANT, + [0xf9] = INAT_MODRM | INAT_VARIANT, + [0xfa] = INAT_MODRM | INAT_VARIANT, + [0xfb] = INAT_MODRM | INAT_VARIANT, + [0xfc] = INAT_MODRM | INAT_VARIANT, + [0xfd] = INAT_MODRM | INAT_VARIANT, + [0xfe] = INAT_MODRM | INAT_VARIANT, }; const insn_attr_t inat_escape_table_1_1[INAT_OPCODE_TABLE_SIZE] = { - [0x10] = INAT_MODRM | INAT_VEXOK, - [0x11] = INAT_MODRM | INAT_VEXOK, - [0x12] = INAT_MODRM | INAT_VEXOK, - [0x13] = INAT_MODRM | INAT_VEXOK, - [0x14] = INAT_MODRM | INAT_VEXOK, - [0x15] = INAT_MODRM | INAT_VEXOK, - [0x16] = INAT_MODRM | INAT_VEXOK, - [0x17] = INAT_MODRM | INAT_VEXOK, - [0x28] = INAT_MODRM | INAT_VEXOK, - [0x29] = INAT_MODRM | INAT_VEXOK, - [0x2a] = INAT_MODRM, - [0x2b] = INAT_MODRM | INAT_VEXOK, - [0x2c] = INAT_MODRM, - [0x2d] = INAT_MODRM, - [0x2e] = INAT_MODRM | INAT_VEXOK, - [0x2f] = INAT_MODRM | INAT_VEXOK, - [0x50] = INAT_MODRM | INAT_VEXOK, - [0x51] = INAT_MODRM | INAT_VEXOK, - [0x54] = INAT_MODRM | INAT_VEXOK, - [0x55] = INAT_MODRM | INAT_VEXOK, - [0x56] = INAT_MODRM | INAT_VEXOK, - [0x57] = INAT_MODRM | INAT_VEXOK, - [0x58] = INAT_MODRM | INAT_VEXOK, - [0x59] = INAT_MODRM | INAT_VEXOK, - [0x5a] = INAT_MODRM | INAT_VEXOK, - [0x5b] = INAT_MODRM | INAT_VEXOK, - [0x5c] = INAT_MODRM | INAT_VEXOK, - [0x5d] = INAT_MODRM | INAT_VEXOK, - [0x5e] = INAT_MODRM | INAT_VEXOK, - [0x5f] = INAT_MODRM | INAT_VEXOK, - [0x60] = INAT_MODRM | INAT_VEXOK, - [0x61] = INAT_MODRM | INAT_VEXOK, - [0x62] = INAT_MODRM | INAT_VEXOK, - [0x63] = INAT_MODRM | INAT_VEXOK, - [0x64] = INAT_MODRM | INAT_VEXOK, - [0x65] = INAT_MODRM | INAT_VEXOK, - [0x66] = INAT_MODRM | INAT_VEXOK, - [0x67] = INAT_MODRM | INAT_VEXOK, - [0x68] = INAT_MODRM | INAT_VEXOK, - [0x69] = INAT_MODRM | INAT_VEXOK, - [0x6a] = INAT_MODRM | INAT_VEXOK, - [0x6b] = INAT_MODRM | INAT_VEXOK, - [0x6c] = INAT_MODRM | INAT_VEXOK, - [0x6d] = INAT_MODRM | INAT_VEXOK, - [0x6e] = INAT_MODRM | INAT_VEXOK, - [0x6f] = INAT_MODRM | INAT_VEXOK, - [0x70] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x74] = INAT_MODRM | INAT_VEXOK, - [0x75] = INAT_MODRM | INAT_VEXOK, - [0x76] = INAT_MODRM | INAT_VEXOK, - [0x7c] = INAT_MODRM | INAT_VEXOK, - [0x7d] = INAT_MODRM | INAT_VEXOK, - [0x7e] = INAT_MODRM | INAT_VEXOK, - [0x7f] = INAT_MODRM | INAT_VEXOK, - [0xbc] = INAT_MODRM, - [0xbd] = INAT_MODRM, - [0xc2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0xc4] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0xc5] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0xc6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0xd0] = INAT_MODRM | INAT_VEXOK, - [0xd1] = INAT_MODRM | INAT_VEXOK, - [0xd2] = INAT_MODRM | INAT_VEXOK, - [0xd3] = INAT_MODRM | INAT_VEXOK, - [0xd4] = INAT_MODRM | INAT_VEXOK, - [0xd5] = INAT_MODRM | INAT_VEXOK, - [0xd6] = INAT_MODRM | INAT_VEXOK, - [0xd7] = INAT_MODRM | INAT_VEXOK, - [0xd8] = INAT_MODRM | INAT_VEXOK, - [0xd9] = INAT_MODRM | INAT_VEXOK, - [0xda] = INAT_MODRM | INAT_VEXOK, - [0xdb] = INAT_MODRM | INAT_VEXOK, - [0xdc] = INAT_MODRM | INAT_VEXOK, - [0xdd] = INAT_MODRM | INAT_VEXOK, - [0xde] = INAT_MODRM | INAT_VEXOK, - [0xdf] = INAT_MODRM | INAT_VEXOK, - [0xe0] = INAT_MODRM | INAT_VEXOK, - [0xe1] = INAT_MODRM | INAT_VEXOK, - [0xe2] = INAT_MODRM | INAT_VEXOK, - [0xe3] = INAT_MODRM | INAT_VEXOK, - [0xe4] = INAT_MODRM | INAT_VEXOK, - [0xe5] = INAT_MODRM | INAT_VEXOK, - [0xe6] = INAT_MODRM | INAT_VEXOK, - [0xe7] = INAT_MODRM | INAT_VEXOK, - [0xe8] = INAT_MODRM | INAT_VEXOK, - [0xe9] = INAT_MODRM | INAT_VEXOK, - [0xea] = INAT_MODRM | INAT_VEXOK, - [0xeb] = INAT_MODRM | INAT_VEXOK, - [0xec] = INAT_MODRM | INAT_VEXOK, - [0xed] = INAT_MODRM | INAT_VEXOK, - [0xee] = INAT_MODRM | INAT_VEXOK, - [0xef] = INAT_MODRM | INAT_VEXOK, - [0xf1] = INAT_MODRM | INAT_VEXOK, - [0xf2] = INAT_MODRM | INAT_VEXOK, - [0xf3] = INAT_MODRM | INAT_VEXOK, - [0xf4] = INAT_MODRM | INAT_VEXOK, - [0xf5] = INAT_MODRM | INAT_VEXOK, - [0xf6] = INAT_MODRM | INAT_VEXOK, - [0xf7] = INAT_MODRM | INAT_VEXOK, - [0xf8] = INAT_MODRM | INAT_VEXOK, - [0xf9] = INAT_MODRM | INAT_VEXOK, - [0xfa] = INAT_MODRM | INAT_VEXOK, - [0xfb] = INAT_MODRM | INAT_VEXOK, - [0xfc] = INAT_MODRM | INAT_VEXOK, - [0xfd] = INAT_MODRM | INAT_VEXOK, - [0xfe] = INAT_MODRM | INAT_VEXOK, + [0x10] = INAT_MODRM | INAT_VEXOK, + [0x11] = INAT_MODRM | INAT_VEXOK, + [0x12] = INAT_MODRM | INAT_VEXOK, + [0x13] = INAT_MODRM | INAT_VEXOK, + [0x14] = INAT_MODRM | INAT_VEXOK, + [0x15] = INAT_MODRM | INAT_VEXOK, + [0x16] = INAT_MODRM | INAT_VEXOK, + [0x17] = INAT_MODRM | INAT_VEXOK, + [0x28] = INAT_MODRM | INAT_VEXOK, + [0x29] = INAT_MODRM | INAT_VEXOK, + [0x2a] = INAT_MODRM, + [0x2b] = INAT_MODRM | INAT_VEXOK, + [0x2c] = INAT_MODRM, + [0x2d] = INAT_MODRM, + [0x2e] = INAT_MODRM | INAT_VEXOK, + [0x2f] = INAT_MODRM | INAT_VEXOK, + [0x50] = INAT_MODRM | INAT_VEXOK, + [0x51] = INAT_MODRM | INAT_VEXOK, + [0x54] = INAT_MODRM | INAT_VEXOK, + [0x55] = INAT_MODRM | INAT_VEXOK, + [0x56] = INAT_MODRM | INAT_VEXOK, + [0x57] = INAT_MODRM | INAT_VEXOK, + [0x58] = INAT_MODRM | INAT_VEXOK, + [0x59] = INAT_MODRM | INAT_VEXOK, + [0x5a] = INAT_MODRM | INAT_VEXOK, + [0x5b] = INAT_MODRM | INAT_VEXOK, + [0x5c] = INAT_MODRM | INAT_VEXOK, + [0x5d] = INAT_MODRM | INAT_VEXOK, + [0x5e] = INAT_MODRM | INAT_VEXOK, + [0x5f] = INAT_MODRM | INAT_VEXOK, + [0x60] = INAT_MODRM | INAT_VEXOK, + [0x61] = INAT_MODRM | INAT_VEXOK, + [0x62] = INAT_MODRM | INAT_VEXOK, + [0x63] = INAT_MODRM | INAT_VEXOK, + [0x64] = INAT_MODRM | INAT_VEXOK, + [0x65] = INAT_MODRM | INAT_VEXOK, + [0x66] = INAT_MODRM | INAT_VEXOK, + [0x67] = INAT_MODRM | INAT_VEXOK, + [0x68] = INAT_MODRM | INAT_VEXOK, + [0x69] = INAT_MODRM | INAT_VEXOK, + [0x6a] = INAT_MODRM | INAT_VEXOK, + [0x6b] = INAT_MODRM | INAT_VEXOK, + [0x6c] = INAT_MODRM | INAT_VEXOK, + [0x6d] = INAT_MODRM | INAT_VEXOK, + [0x6e] = INAT_MODRM | INAT_VEXOK, + [0x6f] = INAT_MODRM | INAT_VEXOK, + [0x70] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x74] = INAT_MODRM | INAT_VEXOK, + [0x75] = INAT_MODRM | INAT_VEXOK, + [0x76] = INAT_MODRM | INAT_VEXOK, + [0x7c] = INAT_MODRM | INAT_VEXOK, + [0x7d] = INAT_MODRM | INAT_VEXOK, + [0x7e] = INAT_MODRM | INAT_VEXOK, + [0x7f] = INAT_MODRM | INAT_VEXOK, + [0xbc] = INAT_MODRM, + [0xbd] = INAT_MODRM, + [0xc2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0xc4] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0xc5] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0xc6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0xd0] = INAT_MODRM | INAT_VEXOK, + [0xd1] = INAT_MODRM | INAT_VEXOK, + [0xd2] = INAT_MODRM | INAT_VEXOK, + [0xd3] = INAT_MODRM | INAT_VEXOK, + [0xd4] = INAT_MODRM | INAT_VEXOK, + [0xd5] = INAT_MODRM | INAT_VEXOK, + [0xd6] = INAT_MODRM | INAT_VEXOK, + [0xd7] = INAT_MODRM | INAT_VEXOK, + [0xd8] = INAT_MODRM | INAT_VEXOK, + [0xd9] = INAT_MODRM | INAT_VEXOK, + [0xda] = INAT_MODRM | INAT_VEXOK, + [0xdb] = INAT_MODRM | INAT_VEXOK, + [0xdc] = INAT_MODRM | INAT_VEXOK, + [0xdd] = INAT_MODRM | INAT_VEXOK, + [0xde] = INAT_MODRM | INAT_VEXOK, + [0xdf] = INAT_MODRM | INAT_VEXOK, + [0xe0] = INAT_MODRM | INAT_VEXOK, + [0xe1] = INAT_MODRM | INAT_VEXOK, + [0xe2] = INAT_MODRM | INAT_VEXOK, + [0xe3] = INAT_MODRM | INAT_VEXOK, + [0xe4] = INAT_MODRM | INAT_VEXOK, + [0xe5] = INAT_MODRM | INAT_VEXOK, + [0xe6] = INAT_MODRM | INAT_VEXOK, + [0xe7] = INAT_MODRM | INAT_VEXOK, + [0xe8] = INAT_MODRM | INAT_VEXOK, + [0xe9] = INAT_MODRM | INAT_VEXOK, + [0xea] = INAT_MODRM | INAT_VEXOK, + [0xeb] = INAT_MODRM | INAT_VEXOK, + [0xec] = INAT_MODRM | INAT_VEXOK, + [0xed] = INAT_MODRM | INAT_VEXOK, + [0xee] = INAT_MODRM | INAT_VEXOK, + [0xef] = INAT_MODRM | INAT_VEXOK, + [0xf1] = INAT_MODRM | INAT_VEXOK, + [0xf2] = INAT_MODRM | INAT_VEXOK, + [0xf3] = INAT_MODRM | INAT_VEXOK, + [0xf4] = INAT_MODRM | INAT_VEXOK, + [0xf5] = INAT_MODRM | INAT_VEXOK, + [0xf6] = INAT_MODRM | INAT_VEXOK, + [0xf7] = INAT_MODRM | INAT_VEXOK, + [0xf8] = INAT_MODRM | INAT_VEXOK, + [0xf9] = INAT_MODRM | INAT_VEXOK, + [0xfa] = INAT_MODRM | INAT_VEXOK, + [0xfb] = INAT_MODRM | INAT_VEXOK, + [0xfc] = INAT_MODRM | INAT_VEXOK, + [0xfd] = INAT_MODRM | INAT_VEXOK, + [0xfe] = INAT_MODRM | INAT_VEXOK, }; const insn_attr_t inat_escape_table_1_2[INAT_OPCODE_TABLE_SIZE] = { - [0x10] = INAT_MODRM | INAT_VEXOK, - [0x11] = INAT_MODRM | INAT_VEXOK, - [0x12] = INAT_MODRM | INAT_VEXOK, - [0x16] = INAT_MODRM | INAT_VEXOK, - [0x2a] = INAT_MODRM | INAT_VEXOK, - [0x2c] = INAT_MODRM | INAT_VEXOK, - [0x2d] = INAT_MODRM | INAT_VEXOK, - [0x51] = INAT_MODRM | INAT_VEXOK, - [0x52] = INAT_MODRM | INAT_VEXOK, - [0x53] = INAT_MODRM | INAT_VEXOK, - [0x58] = INAT_MODRM | INAT_VEXOK, - [0x59] = INAT_MODRM | INAT_VEXOK, - [0x5a] = INAT_MODRM | INAT_VEXOK, - [0x5b] = INAT_MODRM | INAT_VEXOK, - [0x5c] = INAT_MODRM | INAT_VEXOK, - [0x5d] = INAT_MODRM | INAT_VEXOK, - [0x5e] = INAT_MODRM | INAT_VEXOK, - [0x5f] = INAT_MODRM | INAT_VEXOK, - [0x6f] = INAT_MODRM | INAT_VEXOK, - [0x70] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x7e] = INAT_MODRM | INAT_VEXOK, - [0x7f] = INAT_MODRM | INAT_VEXOK, - [0xb8] = INAT_MODRM, - [0xbc] = INAT_MODRM, - [0xbd] = INAT_MODRM, - [0xc2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0xd6] = INAT_MODRM, - [0xe6] = INAT_MODRM | INAT_VEXOK, + [0x10] = INAT_MODRM | INAT_VEXOK, + [0x11] = INAT_MODRM | INAT_VEXOK, + [0x12] = INAT_MODRM | INAT_VEXOK, + [0x16] = INAT_MODRM | INAT_VEXOK, + [0x2a] = INAT_MODRM | INAT_VEXOK, + [0x2c] = INAT_MODRM | INAT_VEXOK, + [0x2d] = INAT_MODRM | INAT_VEXOK, + [0x51] = INAT_MODRM | INAT_VEXOK, + [0x52] = INAT_MODRM | INAT_VEXOK, + [0x53] = INAT_MODRM | INAT_VEXOK, + [0x58] = INAT_MODRM | INAT_VEXOK, + [0x59] = INAT_MODRM | INAT_VEXOK, + [0x5a] = INAT_MODRM | INAT_VEXOK, + [0x5b] = INAT_MODRM | INAT_VEXOK, + [0x5c] = INAT_MODRM | INAT_VEXOK, + [0x5d] = INAT_MODRM | INAT_VEXOK, + [0x5e] = INAT_MODRM | INAT_VEXOK, + [0x5f] = INAT_MODRM | INAT_VEXOK, + [0x6f] = INAT_MODRM | INAT_VEXOK, + [0x70] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x7e] = INAT_MODRM | INAT_VEXOK, + [0x7f] = INAT_MODRM | INAT_VEXOK, + [0xb8] = INAT_MODRM, + [0xbc] = INAT_MODRM, + [0xbd] = INAT_MODRM, + [0xc2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0xd6] = INAT_MODRM, + [0xe6] = INAT_MODRM | INAT_VEXOK, }; const insn_attr_t inat_escape_table_1_3[INAT_OPCODE_TABLE_SIZE] = { - [0x10] = INAT_MODRM | INAT_VEXOK, - [0x11] = INAT_MODRM | INAT_VEXOK, - [0x12] = INAT_MODRM | INAT_VEXOK, - [0x2a] = INAT_MODRM | INAT_VEXOK, - [0x2c] = INAT_MODRM | INAT_VEXOK, - [0x2d] = INAT_MODRM | INAT_VEXOK, - [0x51] = INAT_MODRM | INAT_VEXOK, - [0x58] = INAT_MODRM | INAT_VEXOK, - [0x59] = INAT_MODRM | INAT_VEXOK, - [0x5a] = INAT_MODRM | INAT_VEXOK, - [0x5c] = INAT_MODRM | INAT_VEXOK, - [0x5d] = INAT_MODRM | INAT_VEXOK, - [0x5e] = INAT_MODRM | INAT_VEXOK, - [0x5f] = INAT_MODRM | INAT_VEXOK, - [0x70] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x7c] = INAT_MODRM | INAT_VEXOK, - [0x7d] = INAT_MODRM | INAT_VEXOK, - [0xbc] = INAT_MODRM, - [0xbd] = INAT_MODRM, - [0xc2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0xd0] = INAT_MODRM | INAT_VEXOK, - [0xd6] = INAT_MODRM, - [0xe6] = INAT_MODRM | INAT_VEXOK, - [0xf0] = INAT_MODRM | INAT_VEXOK, + [0x10] = INAT_MODRM | INAT_VEXOK, + [0x11] = INAT_MODRM | INAT_VEXOK, + [0x12] = INAT_MODRM | INAT_VEXOK, + [0x2a] = INAT_MODRM | INAT_VEXOK, + [0x2c] = INAT_MODRM | INAT_VEXOK, + [0x2d] = INAT_MODRM | INAT_VEXOK, + [0x51] = INAT_MODRM | INAT_VEXOK, + [0x58] = INAT_MODRM | INAT_VEXOK, + [0x59] = INAT_MODRM | INAT_VEXOK, + [0x5a] = INAT_MODRM | INAT_VEXOK, + [0x5c] = INAT_MODRM | INAT_VEXOK, + [0x5d] = INAT_MODRM | INAT_VEXOK, + [0x5e] = INAT_MODRM | INAT_VEXOK, + [0x5f] = INAT_MODRM | INAT_VEXOK, + [0x70] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x7c] = INAT_MODRM | INAT_VEXOK, + [0x7d] = INAT_MODRM | INAT_VEXOK, + [0xbc] = INAT_MODRM, + [0xbd] = INAT_MODRM, + [0xc2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0xd0] = INAT_MODRM | INAT_VEXOK, + [0xd6] = INAT_MODRM, + [0xe6] = INAT_MODRM | INAT_VEXOK, + [0xf0] = INAT_MODRM | INAT_VEXOK, }; /* Table: 3-byte opcode 1 (0x0f 0x38) */ const insn_attr_t inat_escape_table_2[INAT_OPCODE_TABLE_SIZE] = { - [0x00] = INAT_MODRM | INAT_VARIANT, - [0x01] = INAT_MODRM | INAT_VARIANT, - [0x02] = INAT_MODRM | INAT_VARIANT, - [0x03] = INAT_MODRM | INAT_VARIANT, - [0x04] = INAT_MODRM | INAT_VARIANT, - [0x05] = INAT_MODRM | INAT_VARIANT, - [0x06] = INAT_MODRM | INAT_VARIANT, - [0x07] = INAT_MODRM | INAT_VARIANT, - [0x08] = INAT_MODRM | INAT_VARIANT, - [0x09] = INAT_MODRM | INAT_VARIANT, - [0x0a] = INAT_MODRM | INAT_VARIANT, - [0x0b] = INAT_MODRM | INAT_VARIANT, - [0x0c] = INAT_VARIANT, - [0x0d] = INAT_VARIANT, - [0x0e] = INAT_VARIANT, - [0x0f] = INAT_VARIANT, - [0x10] = INAT_VARIANT, - [0x13] = INAT_VARIANT, - [0x14] = INAT_VARIANT, - [0x15] = INAT_VARIANT, - [0x16] = INAT_VARIANT, - [0x17] = INAT_VARIANT, - [0x18] = INAT_VARIANT, - [0x19] = INAT_VARIANT, - [0x1a] = INAT_VARIANT, - [0x1c] = INAT_MODRM | INAT_VARIANT, - [0x1d] = INAT_MODRM | INAT_VARIANT, - [0x1e] = INAT_MODRM | INAT_VARIANT, - [0x20] = INAT_VARIANT, - [0x21] = INAT_VARIANT, - [0x22] = INAT_VARIANT, - [0x23] = INAT_VARIANT, - [0x24] = INAT_VARIANT, - [0x25] = INAT_VARIANT, - [0x28] = INAT_VARIANT, - [0x29] = INAT_VARIANT, - [0x2a] = INAT_VARIANT, - [0x2b] = INAT_VARIANT, - [0x2c] = INAT_VARIANT, - [0x2d] = INAT_VARIANT, - [0x2e] = INAT_VARIANT, - [0x2f] = INAT_VARIANT, - [0x30] = INAT_VARIANT, - [0x31] = INAT_VARIANT, - [0x32] = INAT_VARIANT, - [0x33] = INAT_VARIANT, - [0x34] = INAT_VARIANT, - [0x35] = INAT_VARIANT, - [0x36] = INAT_VARIANT, - [0x37] = INAT_VARIANT, - [0x38] = INAT_VARIANT, - [0x39] = INAT_VARIANT, - [0x3a] = INAT_VARIANT, - [0x3b] = INAT_VARIANT, - [0x3c] = INAT_VARIANT, - [0x3d] = INAT_VARIANT, - [0x3e] = INAT_VARIANT, - [0x3f] = INAT_VARIANT, - [0x40] = INAT_VARIANT, - [0x41] = INAT_VARIANT, - [0x45] = INAT_VARIANT, - [0x46] = INAT_VARIANT, - [0x47] = INAT_VARIANT, - [0x58] = INAT_VARIANT, - [0x59] = INAT_VARIANT, - [0x5a] = INAT_VARIANT, - [0x78] = INAT_VARIANT, - [0x79] = INAT_VARIANT, - [0x80] = INAT_VARIANT, - [0x81] = INAT_VARIANT, - [0x82] = INAT_VARIANT, - [0x8c] = INAT_VARIANT, - [0x8e] = INAT_VARIANT, - [0x90] = INAT_VARIANT, - [0x91] = INAT_VARIANT, - [0x92] = INAT_VARIANT, - [0x93] = INAT_VARIANT, - [0x96] = INAT_VARIANT, - [0x97] = INAT_VARIANT, - [0x98] = INAT_VARIANT, - [0x99] = INAT_VARIANT, - [0x9a] = INAT_VARIANT, - [0x9b] = INAT_VARIANT, - [0x9c] = INAT_VARIANT, - [0x9d] = INAT_VARIANT, - [0x9e] = INAT_VARIANT, - [0x9f] = INAT_VARIANT, - [0xa6] = INAT_VARIANT, - [0xa7] = INAT_VARIANT, - [0xa8] = INAT_VARIANT, - [0xa9] = INAT_VARIANT, - [0xaa] = INAT_VARIANT, - [0xab] = INAT_VARIANT, - [0xac] = INAT_VARIANT, - [0xad] = INAT_VARIANT, - [0xae] = INAT_VARIANT, - [0xaf] = INAT_VARIANT, - [0xb6] = INAT_VARIANT, - [0xb7] = INAT_VARIANT, - [0xb8] = INAT_VARIANT, - [0xb9] = INAT_VARIANT, - [0xba] = INAT_VARIANT, - [0xbb] = INAT_VARIANT, - [0xbc] = INAT_VARIANT, - [0xbd] = INAT_VARIANT, - [0xbe] = INAT_VARIANT, - [0xbf] = INAT_VARIANT, - [0xdb] = INAT_VARIANT, - [0xdc] = INAT_VARIANT, - [0xdd] = INAT_VARIANT, - [0xde] = INAT_VARIANT, - [0xdf] = INAT_VARIANT, - [0xf0] = INAT_MODRM | INAT_MODRM | INAT_VARIANT, - [0xf1] = INAT_MODRM | INAT_MODRM | INAT_VARIANT, - [0xf2] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xf3] = INAT_MAKE_GROUP(23), - [0xf5] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY | INAT_VARIANT, - [0xf6] = INAT_VARIANT, - [0xf7] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY | INAT_VARIANT, + [0x00] = INAT_MODRM | INAT_VARIANT, + [0x01] = INAT_MODRM | INAT_VARIANT, + [0x02] = INAT_MODRM | INAT_VARIANT, + [0x03] = INAT_MODRM | INAT_VARIANT, + [0x04] = INAT_MODRM | INAT_VARIANT, + [0x05] = INAT_MODRM | INAT_VARIANT, + [0x06] = INAT_MODRM | INAT_VARIANT, + [0x07] = INAT_MODRM | INAT_VARIANT, + [0x08] = INAT_MODRM | INAT_VARIANT, + [0x09] = INAT_MODRM | INAT_VARIANT, + [0x0a] = INAT_MODRM | INAT_VARIANT, + [0x0b] = INAT_MODRM | INAT_VARIANT, + [0x0c] = INAT_VARIANT, + [0x0d] = INAT_VARIANT, + [0x0e] = INAT_VARIANT, + [0x0f] = INAT_VARIANT, + [0x10] = INAT_VARIANT, + [0x13] = INAT_VARIANT, + [0x14] = INAT_VARIANT, + [0x15] = INAT_VARIANT, + [0x16] = INAT_VARIANT, + [0x17] = INAT_VARIANT, + [0x18] = INAT_VARIANT, + [0x19] = INAT_VARIANT, + [0x1a] = INAT_VARIANT, + [0x1c] = INAT_MODRM | INAT_VARIANT, + [0x1d] = INAT_MODRM | INAT_VARIANT, + [0x1e] = INAT_MODRM | INAT_VARIANT, + [0x20] = INAT_VARIANT, + [0x21] = INAT_VARIANT, + [0x22] = INAT_VARIANT, + [0x23] = INAT_VARIANT, + [0x24] = INAT_VARIANT, + [0x25] = INAT_VARIANT, + [0x28] = INAT_VARIANT, + [0x29] = INAT_VARIANT, + [0x2a] = INAT_VARIANT, + [0x2b] = INAT_VARIANT, + [0x2c] = INAT_VARIANT, + [0x2d] = INAT_VARIANT, + [0x2e] = INAT_VARIANT, + [0x2f] = INAT_VARIANT, + [0x30] = INAT_VARIANT, + [0x31] = INAT_VARIANT, + [0x32] = INAT_VARIANT, + [0x33] = INAT_VARIANT, + [0x34] = INAT_VARIANT, + [0x35] = INAT_VARIANT, + [0x36] = INAT_VARIANT, + [0x37] = INAT_VARIANT, + [0x38] = INAT_VARIANT, + [0x39] = INAT_VARIANT, + [0x3a] = INAT_VARIANT, + [0x3b] = INAT_VARIANT, + [0x3c] = INAT_VARIANT, + [0x3d] = INAT_VARIANT, + [0x3e] = INAT_VARIANT, + [0x3f] = INAT_VARIANT, + [0x40] = INAT_VARIANT, + [0x41] = INAT_VARIANT, + [0x45] = INAT_VARIANT, + [0x46] = INAT_VARIANT, + [0x47] = INAT_VARIANT, + [0x58] = INAT_VARIANT, + [0x59] = INAT_VARIANT, + [0x5a] = INAT_VARIANT, + [0x78] = INAT_VARIANT, + [0x79] = INAT_VARIANT, + [0x80] = INAT_VARIANT, + [0x81] = INAT_VARIANT, + [0x82] = INAT_VARIANT, + [0x8c] = INAT_VARIANT, + [0x8e] = INAT_VARIANT, + [0x90] = INAT_VARIANT, + [0x91] = INAT_VARIANT, + [0x92] = INAT_VARIANT, + [0x93] = INAT_VARIANT, + [0x96] = INAT_VARIANT, + [0x97] = INAT_VARIANT, + [0x98] = INAT_VARIANT, + [0x99] = INAT_VARIANT, + [0x9a] = INAT_VARIANT, + [0x9b] = INAT_VARIANT, + [0x9c] = INAT_VARIANT, + [0x9d] = INAT_VARIANT, + [0x9e] = INAT_VARIANT, + [0x9f] = INAT_VARIANT, + [0xa6] = INAT_VARIANT, + [0xa7] = INAT_VARIANT, + [0xa8] = INAT_VARIANT, + [0xa9] = INAT_VARIANT, + [0xaa] = INAT_VARIANT, + [0xab] = INAT_VARIANT, + [0xac] = INAT_VARIANT, + [0xad] = INAT_VARIANT, + [0xae] = INAT_VARIANT, + [0xaf] = INAT_VARIANT, + [0xb6] = INAT_VARIANT, + [0xb7] = INAT_VARIANT, + [0xb8] = INAT_VARIANT, + [0xb9] = INAT_VARIANT, + [0xba] = INAT_VARIANT, + [0xbb] = INAT_VARIANT, + [0xbc] = INAT_VARIANT, + [0xbd] = INAT_VARIANT, + [0xbe] = INAT_VARIANT, + [0xbf] = INAT_VARIANT, + [0xdb] = INAT_VARIANT, + [0xdc] = INAT_VARIANT, + [0xdd] = INAT_VARIANT, + [0xde] = INAT_VARIANT, + [0xdf] = INAT_VARIANT, + [0xf0] = INAT_MODRM | INAT_MODRM | INAT_VARIANT, + [0xf1] = INAT_MODRM | INAT_MODRM | INAT_VARIANT, + [0xf2] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xf3] = INAT_MAKE_GROUP(23), + [0xf5] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY | INAT_VARIANT, + [0xf6] = INAT_VARIANT, + [0xf7] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY | INAT_VARIANT, }; const insn_attr_t inat_escape_table_2_1[INAT_OPCODE_TABLE_SIZE] = { - [0x00] = INAT_MODRM | INAT_VEXOK, - [0x01] = INAT_MODRM | INAT_VEXOK, - [0x02] = INAT_MODRM | INAT_VEXOK, - [0x03] = INAT_MODRM | INAT_VEXOK, - [0x04] = INAT_MODRM | INAT_VEXOK, - [0x05] = INAT_MODRM | INAT_VEXOK, - [0x06] = INAT_MODRM | INAT_VEXOK, - [0x07] = INAT_MODRM | INAT_VEXOK, - [0x08] = INAT_MODRM | INAT_VEXOK, - [0x09] = INAT_MODRM | INAT_VEXOK, - [0x0a] = INAT_MODRM | INAT_VEXOK, - [0x0b] = INAT_MODRM | INAT_VEXOK, - [0x0c] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x0d] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x0e] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x0f] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x10] = INAT_MODRM, - [0x13] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x14] = INAT_MODRM, - [0x15] = INAT_MODRM, - [0x16] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x17] = INAT_MODRM | INAT_VEXOK, - [0x18] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x19] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x1a] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x1c] = INAT_MODRM | INAT_VEXOK, - [0x1d] = INAT_MODRM | INAT_VEXOK, - [0x1e] = INAT_MODRM | INAT_VEXOK, - [0x20] = INAT_MODRM | INAT_VEXOK, - [0x21] = INAT_MODRM | INAT_VEXOK, - [0x22] = INAT_MODRM | INAT_VEXOK, - [0x23] = INAT_MODRM | INAT_VEXOK, - [0x24] = INAT_MODRM | INAT_VEXOK, - [0x25] = INAT_MODRM | INAT_VEXOK, - [0x28] = INAT_MODRM | INAT_VEXOK, - [0x29] = INAT_MODRM | INAT_VEXOK, - [0x2a] = INAT_MODRM | INAT_VEXOK, - [0x2b] = INAT_MODRM | INAT_VEXOK, - [0x2c] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x2d] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x2e] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x2f] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x30] = INAT_MODRM | INAT_VEXOK, - [0x31] = INAT_MODRM | INAT_VEXOK, - [0x32] = INAT_MODRM | INAT_VEXOK, - [0x33] = INAT_MODRM | INAT_VEXOK, - [0x34] = INAT_MODRM | INAT_VEXOK, - [0x35] = INAT_MODRM | INAT_VEXOK, - [0x36] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x37] = INAT_MODRM | INAT_VEXOK, - [0x38] = INAT_MODRM | INAT_VEXOK, - [0x39] = INAT_MODRM | INAT_VEXOK, - [0x3a] = INAT_MODRM | INAT_VEXOK, - [0x3b] = INAT_MODRM | INAT_VEXOK, - [0x3c] = INAT_MODRM | INAT_VEXOK, - [0x3d] = INAT_MODRM | INAT_VEXOK, - [0x3e] = INAT_MODRM | INAT_VEXOK, - [0x3f] = INAT_MODRM | INAT_VEXOK, - [0x40] = INAT_MODRM | INAT_VEXOK, - [0x41] = INAT_MODRM | INAT_VEXOK, - [0x45] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x46] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x47] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x58] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x59] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x5a] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x78] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x79] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x80] = INAT_MODRM, - [0x81] = INAT_MODRM, - [0x82] = INAT_MODRM, - [0x8c] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x8e] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x90] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x91] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x92] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x93] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x96] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x97] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x98] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x99] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x9a] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x9b] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x9c] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x9d] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x9e] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x9f] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xa6] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xa7] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xa8] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xa9] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xaa] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xab] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xac] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xad] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xae] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xaf] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xb6] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xb7] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xb8] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xb9] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xba] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xbb] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xbc] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xbd] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xbe] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xbf] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xdb] = INAT_MODRM | INAT_VEXOK, - [0xdc] = INAT_MODRM | INAT_VEXOK, - [0xdd] = INAT_MODRM | INAT_VEXOK, - [0xde] = INAT_MODRM | INAT_VEXOK, - [0xdf] = INAT_MODRM | INAT_VEXOK, - [0xf0] = INAT_MODRM, - [0xf1] = INAT_MODRM, - [0xf6] = INAT_MODRM, - [0xf7] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x00] = INAT_MODRM | INAT_VEXOK, + [0x01] = INAT_MODRM | INAT_VEXOK, + [0x02] = INAT_MODRM | INAT_VEXOK, + [0x03] = INAT_MODRM | INAT_VEXOK, + [0x04] = INAT_MODRM | INAT_VEXOK, + [0x05] = INAT_MODRM | INAT_VEXOK, + [0x06] = INAT_MODRM | INAT_VEXOK, + [0x07] = INAT_MODRM | INAT_VEXOK, + [0x08] = INAT_MODRM | INAT_VEXOK, + [0x09] = INAT_MODRM | INAT_VEXOK, + [0x0a] = INAT_MODRM | INAT_VEXOK, + [0x0b] = INAT_MODRM | INAT_VEXOK, + [0x0c] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x0d] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x0e] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x0f] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x10] = INAT_MODRM, + [0x13] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x14] = INAT_MODRM, + [0x15] = INAT_MODRM, + [0x16] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x17] = INAT_MODRM | INAT_VEXOK, + [0x18] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x19] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x1a] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x1c] = INAT_MODRM | INAT_VEXOK, + [0x1d] = INAT_MODRM | INAT_VEXOK, + [0x1e] = INAT_MODRM | INAT_VEXOK, + [0x20] = INAT_MODRM | INAT_VEXOK, + [0x21] = INAT_MODRM | INAT_VEXOK, + [0x22] = INAT_MODRM | INAT_VEXOK, + [0x23] = INAT_MODRM | INAT_VEXOK, + [0x24] = INAT_MODRM | INAT_VEXOK, + [0x25] = INAT_MODRM | INAT_VEXOK, + [0x28] = INAT_MODRM | INAT_VEXOK, + [0x29] = INAT_MODRM | INAT_VEXOK, + [0x2a] = INAT_MODRM | INAT_VEXOK, + [0x2b] = INAT_MODRM | INAT_VEXOK, + [0x2c] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x2d] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x2e] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x2f] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x30] = INAT_MODRM | INAT_VEXOK, + [0x31] = INAT_MODRM | INAT_VEXOK, + [0x32] = INAT_MODRM | INAT_VEXOK, + [0x33] = INAT_MODRM | INAT_VEXOK, + [0x34] = INAT_MODRM | INAT_VEXOK, + [0x35] = INAT_MODRM | INAT_VEXOK, + [0x36] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x37] = INAT_MODRM | INAT_VEXOK, + [0x38] = INAT_MODRM | INAT_VEXOK, + [0x39] = INAT_MODRM | INAT_VEXOK, + [0x3a] = INAT_MODRM | INAT_VEXOK, + [0x3b] = INAT_MODRM | INAT_VEXOK, + [0x3c] = INAT_MODRM | INAT_VEXOK, + [0x3d] = INAT_MODRM | INAT_VEXOK, + [0x3e] = INAT_MODRM | INAT_VEXOK, + [0x3f] = INAT_MODRM | INAT_VEXOK, + [0x40] = INAT_MODRM | INAT_VEXOK, + [0x41] = INAT_MODRM | INAT_VEXOK, + [0x45] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x46] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x47] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x58] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x59] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x5a] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x78] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x79] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x80] = INAT_MODRM, + [0x81] = INAT_MODRM, + [0x82] = INAT_MODRM, + [0x8c] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x8e] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x90] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x91] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x92] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x93] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x96] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x97] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x98] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x99] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x9a] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x9b] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x9c] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x9d] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x9e] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x9f] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xa6] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xa7] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xa8] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xa9] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xaa] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xab] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xac] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xad] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xae] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xaf] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xb6] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xb7] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xb8] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xb9] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xba] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xbb] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xbc] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xbd] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xbe] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xbf] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xdb] = INAT_MODRM | INAT_VEXOK, + [0xdc] = INAT_MODRM | INAT_VEXOK, + [0xdd] = INAT_MODRM | INAT_VEXOK, + [0xde] = INAT_MODRM | INAT_VEXOK, + [0xdf] = INAT_MODRM | INAT_VEXOK, + [0xf0] = INAT_MODRM, + [0xf1] = INAT_MODRM, + [0xf6] = INAT_MODRM, + [0xf7] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, }; const insn_attr_t inat_escape_table_2_2[INAT_OPCODE_TABLE_SIZE] = { - [0xf5] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xf6] = INAT_MODRM, - [0xf7] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xf5] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xf6] = INAT_MODRM, + [0xf7] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, }; const insn_attr_t inat_escape_table_2_3[INAT_OPCODE_TABLE_SIZE] = { - [0xf0] = INAT_MODRM | INAT_MODRM, - [0xf1] = INAT_MODRM | INAT_MODRM, - [0xf5] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xf6] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0xf7] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xf0] = INAT_MODRM | INAT_MODRM, + [0xf1] = INAT_MODRM | INAT_MODRM, + [0xf5] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xf6] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xf7] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, }; /* Table: 3-byte opcode 2 (0x0f 0x3a) */ const insn_attr_t inat_escape_table_3[INAT_OPCODE_TABLE_SIZE] = { - [0x00] = INAT_VARIANT, - [0x01] = INAT_VARIANT, - [0x02] = INAT_VARIANT, - [0x04] = INAT_VARIANT, - [0x05] = INAT_VARIANT, - [0x06] = INAT_VARIANT, - [0x08] = INAT_VARIANT, - [0x09] = INAT_VARIANT, - [0x0a] = INAT_VARIANT, - [0x0b] = INAT_VARIANT, - [0x0c] = INAT_VARIANT, - [0x0d] = INAT_VARIANT, - [0x0e] = INAT_VARIANT, - [0x0f] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, - [0x14] = INAT_VARIANT, - [0x15] = INAT_VARIANT, - [0x16] = INAT_VARIANT, - [0x17] = INAT_VARIANT, - [0x18] = INAT_VARIANT, - [0x19] = INAT_VARIANT, - [0x1d] = INAT_VARIANT, - [0x20] = INAT_VARIANT, - [0x21] = INAT_VARIANT, - [0x22] = INAT_VARIANT, - [0x38] = INAT_VARIANT, - [0x39] = INAT_VARIANT, - [0x40] = INAT_VARIANT, - [0x41] = INAT_VARIANT, - [0x42] = INAT_VARIANT, - [0x44] = INAT_VARIANT, - [0x46] = INAT_VARIANT, - [0x4a] = INAT_VARIANT, - [0x4b] = INAT_VARIANT, - [0x4c] = INAT_VARIANT, - [0x60] = INAT_VARIANT, - [0x61] = INAT_VARIANT, - [0x62] = INAT_VARIANT, - [0x63] = INAT_VARIANT, - [0xdf] = INAT_VARIANT, - [0xf0] = INAT_VARIANT, + [0x00] = INAT_VARIANT, + [0x01] = INAT_VARIANT, + [0x02] = INAT_VARIANT, + [0x04] = INAT_VARIANT, + [0x05] = INAT_VARIANT, + [0x06] = INAT_VARIANT, + [0x08] = INAT_VARIANT, + [0x09] = INAT_VARIANT, + [0x0a] = INAT_VARIANT, + [0x0b] = INAT_VARIANT, + [0x0c] = INAT_VARIANT, + [0x0d] = INAT_VARIANT, + [0x0e] = INAT_VARIANT, + [0x0f] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, + [0x14] = INAT_VARIANT, + [0x15] = INAT_VARIANT, + [0x16] = INAT_VARIANT, + [0x17] = INAT_VARIANT, + [0x18] = INAT_VARIANT, + [0x19] = INAT_VARIANT, + [0x1d] = INAT_VARIANT, + [0x20] = INAT_VARIANT, + [0x21] = INAT_VARIANT, + [0x22] = INAT_VARIANT, + [0x38] = INAT_VARIANT, + [0x39] = INAT_VARIANT, + [0x40] = INAT_VARIANT, + [0x41] = INAT_VARIANT, + [0x42] = INAT_VARIANT, + [0x44] = INAT_VARIANT, + [0x46] = INAT_VARIANT, + [0x4a] = INAT_VARIANT, + [0x4b] = INAT_VARIANT, + [0x4c] = INAT_VARIANT, + [0x60] = INAT_VARIANT, + [0x61] = INAT_VARIANT, + [0x62] = INAT_VARIANT, + [0x63] = INAT_VARIANT, + [0xdf] = INAT_VARIANT, + [0xf0] = INAT_VARIANT, }; const insn_attr_t inat_escape_table_3_1[INAT_OPCODE_TABLE_SIZE] = { - [0x00] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x01] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x02] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x04] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x05] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x06] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x08] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x09] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x0a] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x0b] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x0c] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x0d] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x0e] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x0f] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x14] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x15] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x16] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x17] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x18] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x19] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x1d] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x20] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x21] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x22] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x38] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x39] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x40] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x41] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x42] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x44] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x46] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x4a] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x4b] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x4c] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x60] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x61] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x62] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x63] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0xdf] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x00] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x01] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x02] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x04] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x05] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x06] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x08] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x09] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x0a] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x0b] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x0c] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x0d] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x0e] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x0f] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x14] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x15] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x16] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x17] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x18] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x19] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x1d] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x20] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x21] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x22] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x38] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x39] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x40] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x41] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x42] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x44] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x46] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x4a] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x4b] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x4c] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x60] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x61] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x62] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x63] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0xdf] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, }; const insn_attr_t inat_escape_table_3_3[INAT_OPCODE_TABLE_SIZE] = { - [0xf0] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0xf0] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, }; /* GrpTable: Grp1 */ @@ -937,159 +937,159 @@ const insn_attr_t inat_escape_table_3_3[INAT_OPCODE_TABLE_SIZE] = { /* GrpTable: Grp3_1 */ const insn_attr_t inat_group_table_6[INAT_GROUP_TABLE_SIZE] = { - [0x0] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM, - [0x2] = INAT_MODRM, - [0x3] = INAT_MODRM, - [0x4] = INAT_MODRM, - [0x5] = INAT_MODRM, - [0x6] = INAT_MODRM, - [0x7] = INAT_MODRM, + [0x0] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM, + [0x2] = INAT_MODRM, + [0x3] = INAT_MODRM, + [0x4] = INAT_MODRM, + [0x5] = INAT_MODRM, + [0x6] = INAT_MODRM, + [0x7] = INAT_MODRM, }; /* GrpTable: Grp3_2 */ const insn_attr_t inat_group_table_7[INAT_GROUP_TABLE_SIZE] = { - [0x0] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_MODRM, - [0x2] = INAT_MODRM, - [0x3] = INAT_MODRM, - [0x4] = INAT_MODRM, - [0x5] = INAT_MODRM, - [0x6] = INAT_MODRM, - [0x7] = INAT_MODRM, + [0x0] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_MODRM, + [0x2] = INAT_MODRM, + [0x3] = INAT_MODRM, + [0x4] = INAT_MODRM, + [0x5] = INAT_MODRM, + [0x6] = INAT_MODRM, + [0x7] = INAT_MODRM, }; /* GrpTable: Grp4 */ const insn_attr_t inat_group_table_8[INAT_GROUP_TABLE_SIZE] = { - [0x0] = INAT_MODRM, - [0x1] = INAT_MODRM, + [0x0] = INAT_MODRM, + [0x1] = INAT_MODRM, }; /* GrpTable: Grp5 */ const insn_attr_t inat_group_table_9[INAT_GROUP_TABLE_SIZE] = { - [0x0] = INAT_MODRM, - [0x1] = INAT_MODRM, - [0x2] = INAT_MODRM | INAT_FORCE64, - [0x3] = INAT_MODRM, - [0x4] = INAT_MODRM | INAT_FORCE64, - [0x5] = INAT_MODRM, - [0x6] = INAT_MODRM | INAT_FORCE64, + [0x0] = INAT_MODRM, + [0x1] = INAT_MODRM, + [0x2] = INAT_MODRM | INAT_FORCE64, + [0x3] = INAT_MODRM, + [0x4] = INAT_MODRM | INAT_FORCE64, + [0x5] = INAT_MODRM, + [0x6] = INAT_MODRM | INAT_FORCE64, }; /* GrpTable: Grp6 */ const insn_attr_t inat_group_table_10[INAT_GROUP_TABLE_SIZE] = { - [0x0] = INAT_MODRM, - [0x1] = INAT_MODRM, - [0x2] = INAT_MODRM, - [0x3] = INAT_MODRM, - [0x4] = INAT_MODRM, - [0x5] = INAT_MODRM, + [0x0] = INAT_MODRM, + [0x1] = INAT_MODRM, + [0x2] = INAT_MODRM, + [0x3] = INAT_MODRM, + [0x4] = INAT_MODRM, + [0x5] = INAT_MODRM, }; /* GrpTable: Grp7 */ const insn_attr_t inat_group_table_11[INAT_GROUP_TABLE_SIZE] = { - [0x0] = INAT_MODRM, - [0x1] = INAT_MODRM, - [0x2] = INAT_MODRM, - [0x3] = INAT_MODRM, - [0x4] = INAT_MODRM, - [0x6] = INAT_MODRM, - [0x7] = INAT_MODRM, + [0x0] = INAT_MODRM, + [0x1] = INAT_MODRM, + [0x2] = INAT_MODRM, + [0x3] = INAT_MODRM, + [0x4] = INAT_MODRM, + [0x6] = INAT_MODRM, + [0x7] = INAT_MODRM, }; /* GrpTable: Grp8 */ /* GrpTable: Grp9 */ const insn_attr_t inat_group_table_22[INAT_GROUP_TABLE_SIZE] = { - [0x1] = INAT_MODRM, - [0x6] = INAT_MODRM | INAT_MODRM | INAT_VARIANT, - [0x7] = INAT_MODRM | INAT_MODRM | INAT_VARIANT, + [0x1] = INAT_MODRM, + [0x6] = INAT_MODRM | INAT_MODRM | INAT_VARIANT, + [0x7] = INAT_MODRM | INAT_MODRM | INAT_VARIANT, }; const insn_attr_t inat_group_table_22_1[INAT_GROUP_TABLE_SIZE] = { - [0x6] = INAT_MODRM, + [0x6] = INAT_MODRM, }; const insn_attr_t inat_group_table_22_2[INAT_GROUP_TABLE_SIZE] = { - [0x6] = INAT_MODRM, - [0x7] = INAT_MODRM, + [0x6] = INAT_MODRM, + [0x7] = INAT_MODRM, }; /* GrpTable: Grp10 */ /* GrpTable: Grp11A */ const insn_attr_t inat_group_table_4[INAT_GROUP_TABLE_SIZE] = { - [0x0] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM, - [0x7] = INAT_MAKE_IMM(INAT_IMM_BYTE), + [0x0] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM, + [0x7] = INAT_MAKE_IMM(INAT_IMM_BYTE), }; /* GrpTable: Grp11B */ const insn_attr_t inat_group_table_5[INAT_GROUP_TABLE_SIZE] = { - [0x0] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_MODRM, - [0x7] = INAT_MAKE_IMM(INAT_IMM_VWORD32), + [0x0] = INAT_MAKE_IMM(INAT_IMM_VWORD32) | INAT_MODRM, + [0x7] = INAT_MAKE_IMM(INAT_IMM_VWORD32), }; /* GrpTable: Grp12 */ const insn_attr_t inat_group_table_14[INAT_GROUP_TABLE_SIZE] = { - [0x2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, - [0x4] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, - [0x6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, + [0x2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, + [0x4] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, + [0x6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, }; const insn_attr_t inat_group_table_14_1[INAT_GROUP_TABLE_SIZE] = { - [0x2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x4] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x4] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, }; /* GrpTable: Grp13 */ const insn_attr_t inat_group_table_15[INAT_GROUP_TABLE_SIZE] = { - [0x2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, - [0x4] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, - [0x6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, + [0x2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, + [0x4] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, + [0x6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, }; const insn_attr_t inat_group_table_15_1[INAT_GROUP_TABLE_SIZE] = { - [0x2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x4] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x4] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, }; /* GrpTable: Grp14 */ const insn_attr_t inat_group_table_16[INAT_GROUP_TABLE_SIZE] = { - [0x2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, - [0x3] = INAT_VARIANT, - [0x6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, - [0x7] = INAT_VARIANT, + [0x2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, + [0x3] = INAT_VARIANT, + [0x6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VARIANT, + [0x7] = INAT_VARIANT, }; const insn_attr_t inat_group_table_16_1[INAT_GROUP_TABLE_SIZE] = { - [0x2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x3] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, - [0x7] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x2] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x3] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x6] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, + [0x7] = INAT_MAKE_IMM(INAT_IMM_BYTE) | INAT_MODRM | INAT_VEXOK, }; /* GrpTable: Grp15 */ const insn_attr_t inat_group_table_19[INAT_GROUP_TABLE_SIZE] = { - [0x0] = INAT_VARIANT, - [0x1] = INAT_VARIANT, - [0x2] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, - [0x3] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x0] = INAT_VARIANT, + [0x1] = INAT_VARIANT, + [0x2] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, + [0x3] = INAT_MODRM | INAT_VEXOK | INAT_VARIANT, }; const insn_attr_t inat_group_table_19_2[INAT_GROUP_TABLE_SIZE] = { - [0x0] = INAT_MODRM, - [0x1] = INAT_MODRM, - [0x2] = INAT_MODRM, - [0x3] = INAT_MODRM, + [0x0] = INAT_MODRM, + [0x1] = INAT_MODRM, + [0x2] = INAT_MODRM, + [0x3] = INAT_MODRM, }; /* GrpTable: Grp16 */ const insn_attr_t inat_group_table_13[INAT_GROUP_TABLE_SIZE] = { - [0x0] = INAT_MODRM, - [0x1] = INAT_MODRM, - [0x2] = INAT_MODRM, - [0x3] = INAT_MODRM, + [0x0] = INAT_MODRM, + [0x1] = INAT_MODRM, + [0x2] = INAT_MODRM, + [0x3] = INAT_MODRM, }; /* GrpTable: Grp17 */ const insn_attr_t inat_group_table_23[INAT_GROUP_TABLE_SIZE] = { - [0x1] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x2] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, - [0x3] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x1] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x2] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, + [0x3] = INAT_MODRM | INAT_VEXOK | INAT_VEXONLY, }; /* GrpTable: GrpP */ @@ -1100,57 +1100,57 @@ const insn_attr_t inat_group_table_23[INAT_GROUP_TABLE_SIZE] = { /* Escape opcode map array */ const insn_attr_t * const inat_escape_tables[INAT_ESC_MAX + 1][INAT_LSTPFX_MAX + 1] = { - [1][0] = inat_escape_table_1, - [1][1] = inat_escape_table_1_1, - [1][2] = inat_escape_table_1_2, - [1][3] = inat_escape_table_1_3, - [2][0] = inat_escape_table_2, - [2][1] = inat_escape_table_2_1, - [2][2] = inat_escape_table_2_2, - [2][3] = inat_escape_table_2_3, - [3][0] = inat_escape_table_3, - [3][1] = inat_escape_table_3_1, - [3][3] = inat_escape_table_3_3, + [1][0] = inat_escape_table_1, + [1][1] = inat_escape_table_1_1, + [1][2] = inat_escape_table_1_2, + [1][3] = inat_escape_table_1_3, + [2][0] = inat_escape_table_2, + [2][1] = inat_escape_table_2_1, + [2][2] = inat_escape_table_2_2, + [2][3] = inat_escape_table_2_3, + [3][0] = inat_escape_table_3, + [3][1] = inat_escape_table_3_1, + [3][3] = inat_escape_table_3_3, }; /* Group opcode map array */ const insn_attr_t * const inat_group_tables[INAT_GRP_MAX + 1][INAT_LSTPFX_MAX + 1] = { - [4][0] = inat_group_table_4, - [5][0] = inat_group_table_5, - [6][0] = inat_group_table_6, - [7][0] = inat_group_table_7, - [8][0] = inat_group_table_8, - [9][0] = inat_group_table_9, - [10][0] = inat_group_table_10, - [11][0] = inat_group_table_11, - [13][0] = inat_group_table_13, - [14][0] = inat_group_table_14, - [14][1] = inat_group_table_14_1, - [15][0] = inat_group_table_15, - [15][1] = inat_group_table_15_1, - [16][0] = inat_group_table_16, - [16][1] = inat_group_table_16_1, - [19][0] = inat_group_table_19, - [19][2] = inat_group_table_19_2, - [22][0] = inat_group_table_22, - [22][1] = inat_group_table_22_1, - [22][2] = inat_group_table_22_2, - [23][0] = inat_group_table_23, + [4][0] = inat_group_table_4, + [5][0] = inat_group_table_5, + [6][0] = inat_group_table_6, + [7][0] = inat_group_table_7, + [8][0] = inat_group_table_8, + [9][0] = inat_group_table_9, + [10][0] = inat_group_table_10, + [11][0] = inat_group_table_11, + [13][0] = inat_group_table_13, + [14][0] = inat_group_table_14, + [14][1] = inat_group_table_14_1, + [15][0] = inat_group_table_15, + [15][1] = inat_group_table_15_1, + [16][0] = inat_group_table_16, + [16][1] = inat_group_table_16_1, + [19][0] = inat_group_table_19, + [19][2] = inat_group_table_19_2, + [22][0] = inat_group_table_22, + [22][1] = inat_group_table_22_1, + [22][2] = inat_group_table_22_2, + [23][0] = inat_group_table_23, }; /* AVX opcode map array */ const insn_attr_t * const inat_avx_tables[X86_VEX_M_MAX + 1][INAT_LSTPFX_MAX + 1] = { - [1][0] = inat_escape_table_1, - [1][1] = inat_escape_table_1_1, - [1][2] = inat_escape_table_1_2, - [1][3] = inat_escape_table_1_3, - [2][0] = inat_escape_table_2, - [2][1] = inat_escape_table_2_1, - [2][2] = inat_escape_table_2_2, - [2][3] = inat_escape_table_2_3, - [3][0] = inat_escape_table_3, - [3][1] = inat_escape_table_3_1, - [3][3] = inat_escape_table_3_3, + [1][0] = inat_escape_table_1, + [1][1] = inat_escape_table_1_1, + [1][2] = inat_escape_table_1_2, + [1][3] = inat_escape_table_1_3, + [2][0] = inat_escape_table_2, + [2][1] = inat_escape_table_2_1, + [2][2] = inat_escape_table_2_2, + [2][3] = inat_escape_table_2_3, + [3][0] = inat_escape_table_3, + [3][1] = inat_escape_table_3_1, + [3][3] = inat_escape_table_3_3, }; #endif diff --git a/upatch-diff/insn/asm/inat.h b/upatch-diff/insn/asm/inat.h index 4ab84d6c..887ddfe0 100644 --- a/upatch-diff/insn/asm/inat.h +++ b/upatch-diff/insn/asm/inat.h @@ -33,191 +33,189 @@ #define INAT_GROUP_TABLE_SIZE 8 /* Legacy last prefixes */ -#define INAT_PFX_OPNDSZ 1 /* 0x66 */ /* LPFX1 */ -#define INAT_PFX_REPE 2 /* 0xF3 */ /* LPFX2 */ -#define INAT_PFX_REPNE 3 /* 0xF2 */ /* LPFX3 */ +#define INAT_PFX_OPNDSZ 1 /* 0x66 */ /* LPFX1 */ +#define INAT_PFX_REPE 2 /* 0xF3 */ /* LPFX2 */ +#define INAT_PFX_REPNE 3 /* 0xF2 */ /* LPFX3 */ /* Other Legacy prefixes */ -#define INAT_PFX_LOCK 4 /* 0xF0 */ -#define INAT_PFX_CS 5 /* 0x2E */ -#define INAT_PFX_DS 6 /* 0x3E */ -#define INAT_PFX_ES 7 /* 0x26 */ -#define INAT_PFX_FS 8 /* 0x64 */ -#define INAT_PFX_GS 9 /* 0x65 */ -#define INAT_PFX_SS 10 /* 0x36 */ -#define INAT_PFX_ADDRSZ 11 /* 0x67 */ +#define INAT_PFX_LOCK 4 /* 0xF0 */ +#define INAT_PFX_CS 5 /* 0x2E */ +#define INAT_PFX_DS 6 /* 0x3E */ +#define INAT_PFX_ES 7 /* 0x26 */ +#define INAT_PFX_FS 8 /* 0x64 */ +#define INAT_PFX_GS 9 /* 0x65 */ +#define INAT_PFX_SS 10 /* 0x36 */ +#define INAT_PFX_ADDRSZ 11 /* 0x67 */ /* x86-64 REX prefix */ -#define INAT_PFX_REX 12 /* 0x4X */ +#define INAT_PFX_REX 12 /* 0x4X */ /* AVX VEX prefixes */ -#define INAT_PFX_VEX2 13 /* 2-bytes VEX prefix */ -#define INAT_PFX_VEX3 14 /* 3-bytes VEX prefix */ +#define INAT_PFX_VEX2 13 /* 2-bytes VEX prefix */ +#define INAT_PFX_VEX3 14 /* 3-bytes VEX prefix */ -#define INAT_LSTPFX_MAX 3 -#define INAT_LGCPFX_MAX 11 +#define INAT_LSTPFX_MAX 3 +#define INAT_LGCPFX_MAX 11 /* Immediate size */ -#define INAT_IMM_BYTE 1 -#define INAT_IMM_WORD 2 -#define INAT_IMM_DWORD 3 -#define INAT_IMM_QWORD 4 -#define INAT_IMM_PTR 5 -#define INAT_IMM_VWORD32 6 -#define INAT_IMM_VWORD 7 +#define INAT_IMM_BYTE 1 +#define INAT_IMM_WORD 2 +#define INAT_IMM_DWORD 3 +#define INAT_IMM_QWORD 4 +#define INAT_IMM_PTR 5 +#define INAT_IMM_VWORD32 6 +#define INAT_IMM_VWORD 7 /* Legacy prefix */ -#define INAT_PFX_OFFS 0 -#define INAT_PFX_BITS 4 -#define INAT_PFX_MAX ((1 << INAT_PFX_BITS) - 1) -#define INAT_PFX_MASK (INAT_PFX_MAX << INAT_PFX_OFFS) +#define INAT_PFX_OFFS 0 +#define INAT_PFX_BITS 4 +#define INAT_PFX_MAX ((1 << INAT_PFX_BITS) - 1) +#define INAT_PFX_MASK (INAT_PFX_MAX << INAT_PFX_OFFS) /* Escape opcodes */ -#define INAT_ESC_OFFS (INAT_PFX_OFFS + INAT_PFX_BITS) -#define INAT_ESC_BITS 2 -#define INAT_ESC_MAX ((1 << INAT_ESC_BITS) - 1) -#define INAT_ESC_MASK (INAT_ESC_MAX << INAT_ESC_OFFS) +#define INAT_ESC_OFFS (INAT_PFX_OFFS + INAT_PFX_BITS) +#define INAT_ESC_BITS 2 +#define INAT_ESC_MAX ((1 << INAT_ESC_BITS) - 1) +#define INAT_ESC_MASK (INAT_ESC_MAX << INAT_ESC_OFFS) /* Group opcodes (1-16) */ -#define INAT_GRP_OFFS (INAT_ESC_OFFS + INAT_ESC_BITS) -#define INAT_GRP_BITS 5 -#define INAT_GRP_MAX ((1 << INAT_GRP_BITS) - 1) -#define INAT_GRP_MASK (INAT_GRP_MAX << INAT_GRP_OFFS) +#define INAT_GRP_OFFS (INAT_ESC_OFFS + INAT_ESC_BITS) +#define INAT_GRP_BITS 5 +#define INAT_GRP_MAX ((1 << INAT_GRP_BITS) - 1) +#define INAT_GRP_MASK (INAT_GRP_MAX << INAT_GRP_OFFS) /* Immediates */ -#define INAT_IMM_OFFS (INAT_GRP_OFFS + INAT_GRP_BITS) -#define INAT_IMM_BITS 3 -#define INAT_IMM_MASK (((1 << INAT_IMM_BITS) - 1) << INAT_IMM_OFFS) +#define INAT_IMM_OFFS (INAT_GRP_OFFS + INAT_GRP_BITS) +#define INAT_IMM_BITS 3 +#define INAT_IMM_MASK (((1 << INAT_IMM_BITS) - 1) << INAT_IMM_OFFS) /* Flags */ -#define INAT_FLAG_OFFS (INAT_IMM_OFFS + INAT_IMM_BITS) -#define INAT_MODRM (1 << (INAT_FLAG_OFFS)) -#define INAT_FORCE64 (1 << (INAT_FLAG_OFFS + 1)) -#define INAT_SCNDIMM (1 << (INAT_FLAG_OFFS + 2)) -#define INAT_MOFFSET (1 << (INAT_FLAG_OFFS + 3)) -#define INAT_VARIANT (1 << (INAT_FLAG_OFFS + 4)) -#define INAT_VEXOK (1 << (INAT_FLAG_OFFS + 5)) -#define INAT_VEXONLY (1 << (INAT_FLAG_OFFS + 6)) +#define INAT_FLAG_OFFS (INAT_IMM_OFFS + INAT_IMM_BITS) +#define INAT_MODRM (1 << (INAT_FLAG_OFFS)) +#define INAT_FORCE64 (1 << (INAT_FLAG_OFFS + 1)) +#define INAT_SCNDIMM (1 << (INAT_FLAG_OFFS + 2)) +#define INAT_MOFFSET (1 << (INAT_FLAG_OFFS + 3)) +#define INAT_VARIANT (1 << (INAT_FLAG_OFFS + 4)) +#define INAT_VEXOK (1 << (INAT_FLAG_OFFS + 5)) +#define INAT_VEXONLY (1 << (INAT_FLAG_OFFS + 6)) /* Attribute making macros for attribute tables */ -#define INAT_MAKE_PREFIX(pfx) (pfx << INAT_PFX_OFFS) -#define INAT_MAKE_ESCAPE(esc) (esc << INAT_ESC_OFFS) -#define INAT_MAKE_GROUP(grp) ((grp << INAT_GRP_OFFS) | INAT_MODRM) -#define INAT_MAKE_IMM(imm) (imm << INAT_IMM_OFFS) +#define INAT_MAKE_PREFIX(pfx) ((pfx) << INAT_PFX_OFFS) +#define INAT_MAKE_ESCAPE(esc) ((esc) << INAT_ESC_OFFS) +#define INAT_MAKE_GROUP(grp) (((grp) << INAT_GRP_OFFS) | INAT_MODRM) +#define INAT_MAKE_IMM(imm) ((imm) << INAT_IMM_OFFS) /* Attribute search APIs */ extern insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode); extern int inat_get_last_prefix_id(insn_byte_t last_pfx); extern insn_attr_t inat_get_escape_attribute(insn_byte_t opcode, - int lpfx_id, - insn_attr_t esc_attr); + int lpfx_id, insn_attr_t esc_attr); extern insn_attr_t inat_get_group_attribute(insn_byte_t modrm, - int lpfx_id, - insn_attr_t esc_attr); + int lpfx_id, insn_attr_t esc_attr); extern insn_attr_t inat_get_avx_attribute(insn_byte_t opcode, - insn_byte_t vex_m, - insn_byte_t vex_pp); + insn_byte_t vex_m, insn_byte_t vex_pp); /* Attribute checking functions */ static inline int inat_is_legacy_prefix(insn_attr_t attr) { - attr &= INAT_PFX_MASK; - return attr && attr <= INAT_LGCPFX_MAX; + attr &= INAT_PFX_MASK; + return attr && attr <= INAT_LGCPFX_MAX; } static inline int inat_is_address_size_prefix(insn_attr_t attr) { - return (attr & INAT_PFX_MASK) == INAT_PFX_ADDRSZ; + return (attr & INAT_PFX_MASK) == INAT_PFX_ADDRSZ; } static inline int inat_is_operand_size_prefix(insn_attr_t attr) { - return (attr & INAT_PFX_MASK) == INAT_PFX_OPNDSZ; + return (attr & INAT_PFX_MASK) == INAT_PFX_OPNDSZ; } static inline int inat_is_rex_prefix(insn_attr_t attr) { - return (attr & INAT_PFX_MASK) == INAT_PFX_REX; + return (attr & INAT_PFX_MASK) == INAT_PFX_REX; } static inline int inat_last_prefix_id(insn_attr_t attr) { - if ((attr & INAT_PFX_MASK) > INAT_LSTPFX_MAX) - return 0; - else - return attr & INAT_PFX_MASK; + if ((attr & INAT_PFX_MASK) > INAT_LSTPFX_MAX) { + return 0; + } else { + return attr & INAT_PFX_MASK; + } } static inline int inat_is_vex_prefix(insn_attr_t attr) { - attr &= INAT_PFX_MASK; - return attr == INAT_PFX_VEX2 || attr == INAT_PFX_VEX3; + attr &= INAT_PFX_MASK; + return attr == INAT_PFX_VEX2 || attr == INAT_PFX_VEX3; } static inline int inat_is_vex3_prefix(insn_attr_t attr) { - return (attr & INAT_PFX_MASK) == INAT_PFX_VEX3; + return (attr & INAT_PFX_MASK) == INAT_PFX_VEX3; } static inline int inat_is_escape(insn_attr_t attr) { - return attr & INAT_ESC_MASK; + return attr & INAT_ESC_MASK; } static inline unsigned int inat_escape_id(insn_attr_t attr) { - return (attr & INAT_ESC_MASK) >> INAT_ESC_OFFS; + return (attr & INAT_ESC_MASK) >> INAT_ESC_OFFS; } static inline int inat_is_group(insn_attr_t attr) { - return attr & INAT_GRP_MASK; + return attr & INAT_GRP_MASK; } static inline unsigned int inat_group_id(insn_attr_t attr) { - return (attr & INAT_GRP_MASK) >> INAT_GRP_OFFS; + return (attr & INAT_GRP_MASK) >> INAT_GRP_OFFS; } static inline insn_attr_t inat_group_common_attribute(insn_attr_t attr) { - return attr & ~(insn_attr_t)INAT_GRP_MASK; + return attr & ~(insn_attr_t)INAT_GRP_MASK; } static inline int inat_has_immediate(insn_attr_t attr) { - return attr & INAT_IMM_MASK; + return attr & INAT_IMM_MASK; } static inline unsigned int inat_immediate_size(insn_attr_t attr) { - return (attr & INAT_IMM_MASK) >> INAT_IMM_OFFS; + return (attr & INAT_IMM_MASK) >> INAT_IMM_OFFS; } static inline int inat_has_modrm(insn_attr_t attr) { - return attr & INAT_MODRM; + return attr & INAT_MODRM; } static inline int inat_is_force64(insn_attr_t attr) { - return attr & INAT_FORCE64; + return attr & INAT_FORCE64; } static inline int inat_has_second_immediate(insn_attr_t attr) { - return attr & INAT_SCNDIMM; + return attr & INAT_SCNDIMM; } static inline int inat_has_moffset(insn_attr_t attr) { - return attr & INAT_MOFFSET; + return attr & INAT_MOFFSET; } static inline int inat_has_variant(insn_attr_t attr) { - return attr & INAT_VARIANT; + return attr & INAT_VARIANT; } static inline int inat_accept_vex(insn_attr_t attr) { - return attr & INAT_VEXOK; + return attr & INAT_VEXOK; } static inline int inat_must_vex(insn_attr_t attr) { - return attr & INAT_VEXONLY; + return attr & INAT_VEXONLY; } #endif diff --git a/upatch-diff/insn/asm/insn.h b/upatch-diff/insn/asm/insn.h index fc4ae40f..09cb33d6 100644 --- a/upatch-diff/insn/asm/insn.h +++ b/upatch-diff/insn/asm/insn.h @@ -25,77 +25,77 @@ #include struct insn_field { - union { - insn_value_t value; - insn_byte_t bytes[4]; - }; - /* !0 if we've run insn_get_xxx() for this field */ - unsigned char got; - unsigned char nbytes; + union { + insn_value_t value; + insn_byte_t bytes[4]; + }; + /* !0 if we've run insn_get_xxx() for this field */ + unsigned char got; + unsigned char nbytes; }; struct insn { - struct insn_field prefixes; /* - * Prefixes - * prefixes.bytes[3]: last prefix - */ - struct insn_field rex_prefix; /* REX prefix */ - struct insn_field vex_prefix; /* VEX prefix */ - struct insn_field opcode; /* - * opcode.bytes[0]: opcode1 - * opcode.bytes[1]: opcode2 - * opcode.bytes[2]: opcode3 - */ - struct insn_field modrm; - struct insn_field sib; - struct insn_field displacement; - union { - struct insn_field immediate; - struct insn_field moffset1; /* for 64bit MOV */ - struct insn_field immediate1; /* for 64bit imm or off16/32 */ - }; - union { - struct insn_field moffset2; /* for 64bit MOV */ - struct insn_field immediate2; /* for 64bit imm or seg16 */ - }; - - insn_attr_t attr; - unsigned char opnd_bytes; - unsigned char addr_bytes; - unsigned char length; - unsigned char x86_64; - - const insn_byte_t *kaddr; /* kernel address of insn to analyze */ - insn_byte_t *next_byte; + struct insn_field prefixes; /* + * Prefixes + * prefixes.bytes[3]: last prefix + */ + struct insn_field rex_prefix; /* REX prefix */ + struct insn_field vex_prefix; /* VEX prefix */ + struct insn_field opcode; /* + * opcode.bytes[0]: opcode1 + * opcode.bytes[1]: opcode2 + * opcode.bytes[2]: opcode3 + */ + struct insn_field modrm; + struct insn_field sib; + struct insn_field displacement; + union { + struct insn_field immediate; + struct insn_field moffset1; /* for 64bit MOV */ + struct insn_field immediate1; /* for 64bit imm or off16/32 */ + }; + union { + struct insn_field moffset2; /* for 64bit MOV */ + struct insn_field immediate2; /* for 64bit imm or seg16 */ + }; + + insn_attr_t attr; + unsigned char opnd_bytes; + unsigned char addr_bytes; + unsigned char length; + unsigned char x86_64; + + const insn_byte_t *kaddr; /* kernel address of insn to analyze */ + insn_byte_t *next_byte; }; -#define MAX_INSN_SIZE 16 +#define MAX_INSN_SIZE 16 #define X86_MODRM_MOD(modrm) (((modrm) & 0xc0) >> 6) #define X86_MODRM_REG(modrm) (((modrm) & 0x38) >> 3) -#define X86_MODRM_RM(modrm) ((modrm) & 0x07) +#define X86_MODRM_RM(modrm) ((modrm) & 0x07) #define X86_SIB_SCALE(sib) (((sib) & 0xc0) >> 6) #define X86_SIB_INDEX(sib) (((sib) & 0x38) >> 3) -#define X86_SIB_BASE(sib) ((sib) & 0x07) +#define X86_SIB_BASE(sib) ((sib) & 0x07) -#define X86_REX_W(rex) ((rex) & 8) -#define X86_REX_R(rex) ((rex) & 4) -#define X86_REX_X(rex) ((rex) & 2) -#define X86_REX_B(rex) ((rex) & 1) +#define X86_REX_W(rex) ((rex) & 8) +#define X86_REX_R(rex) ((rex) & 4) +#define X86_REX_X(rex) ((rex) & 2) +#define X86_REX_B(rex) ((rex) & 1) /* VEX bit flags */ -#define X86_VEX_W(vex) ((vex) & 0x80) /* VEX3 Byte2 */ -#define X86_VEX_R(vex) ((vex) & 0x80) /* VEX2/3 Byte1 */ -#define X86_VEX_X(vex) ((vex) & 0x40) /* VEX3 Byte1 */ -#define X86_VEX_B(vex) ((vex) & 0x20) /* VEX3 Byte1 */ -#define X86_VEX_L(vex) ((vex) & 0x04) /* VEX3 Byte2, VEX2 Byte1 */ +#define X86_VEX_W(vex) ((vex) & 0x80) /* VEX3 Byte2 */ +#define X86_VEX_R(vex) ((vex) & 0x80) /* VEX2/3 Byte1 */ +#define X86_VEX_X(vex) ((vex) & 0x40) /* VEX3 Byte1 */ +#define X86_VEX_B(vex) ((vex) & 0x20) /* VEX3 Byte1 */ +#define X86_VEX_L(vex) ((vex) & 0x04) /* VEX3 Byte2, VEX2 Byte1 */ /* VEX bit fields */ -#define X86_VEX3_M(vex) ((vex) & 0x1f) /* VEX3 Byte1 */ -#define X86_VEX2_M 1 /* VEX2.M always 1 */ -#define X86_VEX_V(vex) (((vex) & 0x78) >> 3) /* VEX3 Byte2, VEX2 Byte1 */ -#define X86_VEX_P(vex) ((vex) & 0x03) /* VEX3 Byte2, VEX2 Byte1 */ -#define X86_VEX_M_MAX 0x1f /* VEX3.M Maximum value */ +#define X86_VEX3_M(vex) ((vex) & 0x1f) /* VEX3 Byte1 */ +#define X86_VEX2_M 1 /* VEX2.M always 1 */ +#define X86_VEX_V(vex) (((vex) & 0x78) >> 3) /* VEX3 Byte2, VEX2 Byte1 */ +#define X86_VEX_P(vex) ((vex) & 0x03) /* VEX3 Byte2, VEX2 Byte1 */ +#define X86_VEX_M_MAX 0x1f /* VEX3.M Maximum value */ extern void insn_init(struct insn *insn, void *kaddr, int x86_64); extern void insn_get_prefixes(struct insn *insn); @@ -109,7 +109,7 @@ extern void insn_get_length(struct insn *insn); /* Attribute will be determined after getting ModRM (for opcode groups) */ static inline void insn_get_attribute(struct insn *insn) { - insn_get_modrm(insn); + insn_get_modrm(insn); } /* Instruction uses RIP-relative addressing */ @@ -119,82 +119,95 @@ extern int insn_rip_relative(struct insn *insn); static inline void kernel_insn_init(struct insn *insn, void *kaddr) { #ifdef CONFIG_X86_64 - insn_init(insn, kaddr, 1); + insn_init(insn, kaddr, 1); #else /* CONFIG_X86_32 */ - insn_init(insn, kaddr, 0); + insn_init(insn, kaddr, 0); #endif } static inline int insn_is_avx(struct insn *insn) { - if (!insn->prefixes.got) - insn_get_prefixes(insn); - return (insn->vex_prefix.value != 0); + if (!insn->prefixes.got) { + insn_get_prefixes(insn); + } + return (insn->vex_prefix.value != 0); } /* Ensure this instruction is decoded completely */ static inline int insn_complete(struct insn *insn) { - return insn->opcode.got && insn->modrm.got && insn->sib.got && - insn->displacement.got && insn->immediate.got; + return insn->opcode.got && insn->modrm.got && insn->sib.got && + insn->displacement.got && insn->immediate.got; } static inline insn_byte_t insn_vex_m_bits(struct insn *insn) { - if (insn->vex_prefix.nbytes == 2) /* 2 bytes VEX */ - return X86_VEX2_M; - else - return X86_VEX3_M(insn->vex_prefix.bytes[1]); + if (insn->vex_prefix.nbytes == 2) { + /* 2 bytes VEX */ + return X86_VEX2_M; + } else { + return X86_VEX3_M(insn->vex_prefix.bytes[1]); + } } static inline insn_byte_t insn_vex_p_bits(struct insn *insn) { - if (insn->vex_prefix.nbytes == 2) /* 2 bytes VEX */ - return X86_VEX_P(insn->vex_prefix.bytes[1]); - else - return X86_VEX_P(insn->vex_prefix.bytes[2]); + if (insn->vex_prefix.nbytes == 2) { + /* 2 bytes VEX */ + return X86_VEX_P(insn->vex_prefix.bytes[1]); + } else { + return X86_VEX_P(insn->vex_prefix.bytes[2]); + } } /* Get the last prefix id from last prefix or VEX prefix */ static inline int insn_last_prefix_id(struct insn *insn) { - if (insn_is_avx(insn)) - return insn_vex_p_bits(insn); /* VEX_p is a SIMD prefix id */ + if (insn_is_avx(insn)) { + return insn_vex_p_bits(insn); /* VEX_p is a SIMD prefix id */ + } - if (insn->prefixes.bytes[3]) - return inat_get_last_prefix_id(insn->prefixes.bytes[3]); + if (insn->prefixes.bytes[3]) { + return inat_get_last_prefix_id(insn->prefixes.bytes[3]); + } - return 0; + return 0; } /* Offset of each field from kaddr */ static inline int insn_offset_rex_prefix(struct insn *insn) { - return insn->prefixes.nbytes; + return insn->prefixes.nbytes; } + static inline int insn_offset_vex_prefix(struct insn *insn) { - return insn_offset_rex_prefix(insn) + insn->rex_prefix.nbytes; + return insn_offset_rex_prefix(insn) + insn->rex_prefix.nbytes; } + static inline int insn_offset_opcode(struct insn *insn) { - return insn_offset_vex_prefix(insn) + insn->vex_prefix.nbytes; + return insn_offset_vex_prefix(insn) + insn->vex_prefix.nbytes; } + static inline int insn_offset_modrm(struct insn *insn) { - return insn_offset_opcode(insn) + insn->opcode.nbytes; + return insn_offset_opcode(insn) + insn->opcode.nbytes; } + static inline int insn_offset_sib(struct insn *insn) { - return insn_offset_modrm(insn) + insn->modrm.nbytes; + return insn_offset_modrm(insn) + insn->modrm.nbytes; } + static inline int insn_offset_displacement(struct insn *insn) { - return insn_offset_sib(insn) + insn->sib.nbytes; + return insn_offset_sib(insn) + insn->sib.nbytes; } + static inline int insn_offset_immediate(struct insn *insn) { - return insn_offset_displacement(insn) + insn->displacement.nbytes; + return insn_offset_displacement(insn) + insn->displacement.nbytes; } -#endif /* _ASM_X86_INSN_H */ \ No newline at end of file +#endif /* _ASM_X86_INSN_H */ diff --git a/upatch-diff/insn/inat.c b/upatch-diff/insn/inat.c index cb5aec62..96b01158 100644 --- a/upatch-diff/insn/inat.c +++ b/upatch-diff/insn/inat.c @@ -28,71 +28,78 @@ /* Attribute search APIs */ insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode) { - return inat_primary_table[opcode]; + return inat_primary_table[opcode]; } int inat_get_last_prefix_id(insn_byte_t last_pfx) { - insn_attr_t lpfx_attr; + insn_attr_t lpfx_attr; - lpfx_attr = inat_get_opcode_attribute(last_pfx); - return inat_last_prefix_id(lpfx_attr); + lpfx_attr = inat_get_opcode_attribute(last_pfx); + return inat_last_prefix_id(lpfx_attr); } insn_attr_t inat_get_escape_attribute(insn_byte_t opcode, int lpfx_id, - insn_attr_t esc_attr) + insn_attr_t esc_attr) { - const insn_attr_t *table; - unsigned int n; + const insn_attr_t *table; + unsigned int n; - n = inat_escape_id(esc_attr); + n = inat_escape_id(esc_attr); - table = inat_escape_tables[n][0]; - if (!table) - return 0; - if (inat_has_variant(table[opcode]) && lpfx_id) { - table = inat_escape_tables[n][lpfx_id]; - if (!table) - return 0; - } - return table[opcode]; + table = inat_escape_tables[n][0]; + if (!table) { + return 0; + } + if (inat_has_variant(table[opcode]) && lpfx_id) { + table = inat_escape_tables[n][lpfx_id]; + if (!table) { + return 0; + } + } + return table[opcode]; } insn_attr_t inat_get_group_attribute(insn_byte_t modrm, int lpfx_id, - insn_attr_t grp_attr) + insn_attr_t grp_attr) { - const insn_attr_t *table; - unsigned int n; + const insn_attr_t *table; + unsigned int n; - n = inat_group_id(grp_attr); + n = inat_group_id(grp_attr); - table = inat_group_tables[n][0]; - if (!table) - return inat_group_common_attribute(grp_attr); - if (inat_has_variant(table[X86_MODRM_REG(modrm)]) && lpfx_id) { - table = inat_group_tables[n][lpfx_id]; - if (!table) - return inat_group_common_attribute(grp_attr); - } - return table[X86_MODRM_REG(modrm)] | - inat_group_common_attribute(grp_attr); + table = inat_group_tables[n][0]; + if (!table) { + return inat_group_common_attribute(grp_attr); + } + if (inat_has_variant(table[X86_MODRM_REG(modrm)]) && lpfx_id) { + table = inat_group_tables[n][lpfx_id]; + if (!table) { + return inat_group_common_attribute(grp_attr); + } + } + return table[X86_MODRM_REG(modrm)] | + inat_group_common_attribute(grp_attr); } insn_attr_t inat_get_avx_attribute(insn_byte_t opcode, insn_byte_t vex_m, - insn_byte_t vex_p) + insn_byte_t vex_p) { - const insn_attr_t *table; - if (vex_m > X86_VEX_M_MAX || vex_p > INAT_LSTPFX_MAX) - return 0; - /* At first, this checks the master table */ - table = inat_avx_tables[vex_m][0]; - if (!table) - return 0; - if (!inat_is_group(table[opcode]) && vex_p) { - /* If this is not a group, get attribute directly */ - table = inat_avx_tables[vex_m][vex_p]; - if (!table) - return 0; - } - return table[opcode]; + const insn_attr_t *table; + if (vex_m > X86_VEX_M_MAX || vex_p > INAT_LSTPFX_MAX) { + return 0; + } + /* At first, this checks the master table */ + table = inat_avx_tables[vex_m][0]; + if (!table) { + return 0; + } + if (!inat_is_group(table[opcode]) && vex_p) { + /* If this is not a group, get attribute directly */ + table = inat_avx_tables[vex_m][vex_p]; + if (!table) { + return 0; + } + } + return table[opcode]; } diff --git a/upatch-diff/insn/insn.c b/upatch-diff/insn/insn.c index 7880eedf..d38953c4 100644 --- a/upatch-diff/insn/insn.c +++ b/upatch-diff/insn/insn.c @@ -26,45 +26,46 @@ #define unlikely(a) a /* Verify next sizeof(t) bytes can be on the same instruction */ -#define validate_next(t, insn, n) \ - ((insn)->next_byte + sizeof(t) + n - (insn)->kaddr <= MAX_INSN_SIZE) +#define validate_next(t, insn, n) \ + ((insn)->next_byte + sizeof(t) + (n) - (insn)->kaddr <= MAX_INSN_SIZE) -#define __get_next(t, insn) \ - ({ t r = *(t*)insn->next_byte; insn->next_byte += sizeof(t); r; }) +#define next_type_of(t, insn) \ + ({ t r = *(t*)((insn)->next_byte); (insn)->next_byte += sizeof(t); r; }) -#define __peek_nbyte_next(t, insn, n) \ - ({ t r = *(t*)((insn)->next_byte + n); r; }) +#define peek_nbytes_of(t, insn, n) \ + ({ t r = *(t*)((insn)->next_byte + (n)); r; }) -#define get_next(t, insn) \ - ({ if (unlikely(!validate_next(t, insn, 0))) goto err_out; __get_next(t, insn); }) +#define get_next(t, insn) \ + ({ if (unlikely(!validate_next(t, insn, 0))) goto err_out; next_type_of(t, insn); }) -#define peek_nbyte_next(t, insn, n) \ - ({ if (unlikely(!validate_next(t, insn, n))) goto err_out; __peek_nbyte_next(t, insn, n); }) +#define peek_nbyte_next(t, insn, n) \ + ({ if (unlikely(!validate_next(t, insn, n))) goto err_out; peek_nbytes_of(t, insn, n); }) -#define peek_next(t, insn) peek_nbyte_next(t, insn, 0) +#define peek_next(t, insn) peek_nbyte_next(t, insn, 0) /** * insn_init() - initialize struct insn - * @insn: &struct insn to be initialized - * @kaddr: address (in kernel memory) of instruction (or copy thereof) - * @x86_64: !0 for 64-bit kernel or 64-bit app + * @insn: &struct insn to be initialized + * @kaddr: address (in kernel memory) of instruction (or copy thereof) + * @x86_64: !0 for 64-bit kernel or 64-bit app */ void insn_init(struct insn *insn, void *kaddr, int x86_64) { - memset(insn, 0, sizeof(*insn)); - insn->kaddr = kaddr; - insn->next_byte = kaddr; - insn->x86_64 = x86_64 ? 1 : 0; - insn->opnd_bytes = 4; - if (x86_64) - insn->addr_bytes = 8; - else - insn->addr_bytes = 4; + memset(insn, 0, sizeof(*insn)); + insn->kaddr = kaddr; + insn->next_byte = kaddr; + insn->x86_64 = x86_64 ? 1 : 0; + insn->opnd_bytes = 4; + if (x86_64) { + insn->addr_bytes = 8; + } else { + insn->addr_bytes = 4; + } } /** * insn_get_prefixes - scan x86 instruction prefix bytes - * @insn: &struct insn containing instruction + * @insn: &struct insn containing instruction * * Populates the @insn->prefixes bitmap, and updates @insn->next_byte * to point to the (first) opcode. No effect if @insn->prefixes.got @@ -72,112 +73,124 @@ void insn_init(struct insn *insn, void *kaddr, int x86_64) */ void insn_get_prefixes(struct insn *insn) { - struct insn_field *prefixes = &insn->prefixes; - insn_attr_t attr; - insn_byte_t b, lb; - int i, nb; - - if (prefixes->got) - return; - - nb = 0; - lb = 0; - b = peek_next(insn_byte_t, insn); - attr = inat_get_opcode_attribute(b); - while (inat_is_legacy_prefix(attr)) { - /* Skip if same prefix */ - for (i = 0; i < nb; i++) - if (prefixes->bytes[i] == b) - goto found; - if (nb == 4) - /* Invalid instruction */ - break; - prefixes->bytes[nb++] = b; - if (inat_is_address_size_prefix(attr)) { - /* address size switches 2/4 or 4/8 */ - if (insn->x86_64) - insn->addr_bytes ^= 12; - else - insn->addr_bytes ^= 6; - } else if (inat_is_operand_size_prefix(attr)) { - /* oprand size switches 2/4 */ - insn->opnd_bytes ^= 6; - } + struct insn_field *prefixes = &insn->prefixes; + insn_attr_t attr; + insn_byte_t b; + insn_byte_t lb; + int i; + int nb; + + if (prefixes->got) { + return; + } + + nb = 0; + lb = 0; + b = peek_next(insn_byte_t, insn); + attr = inat_get_opcode_attribute(b); + while (inat_is_legacy_prefix(attr)) { + /* Skip if same prefix */ + for (i = 0; i < nb; i++) { + if (prefixes->bytes[i] == b) { + goto found; + } + } + if (nb == 4) { + /* Invalid instruction */ + break; + } + prefixes->bytes[nb++] = b; + if (inat_is_address_size_prefix(attr)) { + /* address size switches 2/4 or 4/8 */ + if (insn->x86_64) { + insn->addr_bytes ^= 12; + } else { + insn->addr_bytes ^= 6; + } + } else if (inat_is_operand_size_prefix(attr)) { + /* oprand size switches 2/4 */ + insn->opnd_bytes ^= 6; + } found: - prefixes->nbytes++; - insn->next_byte++; - lb = b; - b = peek_next(insn_byte_t, insn); - attr = inat_get_opcode_attribute(b); - } - /* Set the last prefix */ - if (lb && lb != insn->prefixes.bytes[3]) { - if (unlikely(insn->prefixes.bytes[3])) { - /* Swap the last prefix */ - b = insn->prefixes.bytes[3]; - for (i = 0; i < nb; i++) - if (prefixes->bytes[i] == lb) - prefixes->bytes[i] = b; - } - insn->prefixes.bytes[3] = lb; - } - - /* Decode REX prefix */ - if (insn->x86_64) { - b = peek_next(insn_byte_t, insn); - attr = inat_get_opcode_attribute(b); - if (inat_is_rex_prefix(attr)) { - insn->rex_prefix.value = b; - insn->rex_prefix.nbytes = 1; - insn->next_byte++; - if (X86_REX_W(b)) - /* REX.W overrides opnd_size */ - insn->opnd_bytes = 8; - } - } - insn->rex_prefix.got = 1; - - /* Decode VEX prefix */ - b = peek_next(insn_byte_t, insn); - attr = inat_get_opcode_attribute(b); - if (inat_is_vex_prefix(attr)) { - insn_byte_t b2 = peek_nbyte_next(insn_byte_t, insn, 1); - if (!insn->x86_64) { - /* - * In 32-bits mode, if the [7:6] bits (mod bits of - * ModRM) on the second byte are not 11b, it is - * LDS or LES. - */ - if (X86_MODRM_MOD(b2) != 3) - goto vex_end; - } - insn->vex_prefix.bytes[0] = b; - insn->vex_prefix.bytes[1] = b2; - if (inat_is_vex3_prefix(attr)) { - b2 = peek_nbyte_next(insn_byte_t, insn, 2); - insn->vex_prefix.bytes[2] = b2; - insn->vex_prefix.nbytes = 3; - insn->next_byte += 3; - if (insn->x86_64 && X86_VEX_W(b2)) - /* VEX.W overrides opnd_size */ - insn->opnd_bytes = 8; - } else { - insn->vex_prefix.nbytes = 2; - insn->next_byte += 2; - } - } + prefixes->nbytes++; + insn->next_byte++; + lb = b; + b = peek_next(insn_byte_t, insn); + attr = inat_get_opcode_attribute(b); + } + /* Set the last prefix */ + if (lb && lb != insn->prefixes.bytes[3]) { + if (unlikely(insn->prefixes.bytes[3])) { + /* Swap the last prefix */ + b = insn->prefixes.bytes[3]; + for (i = 0; i < nb; i++) { + if (prefixes->bytes[i] == lb) { + prefixes->bytes[i] = b; + } + } + } + insn->prefixes.bytes[3] = lb; + } + + /* Decode REX prefix */ + if (insn->x86_64) { + b = peek_next(insn_byte_t, insn); + attr = inat_get_opcode_attribute(b); + if (inat_is_rex_prefix(attr)) { + insn->rex_prefix.value = b; + insn->rex_prefix.nbytes = 1; + insn->next_byte++; + if (X86_REX_W(b)) { + /* REX.W overrides opnd_size */ + insn->opnd_bytes = 8; + } + } + } + insn->rex_prefix.got = 1; + + /* Decode VEX prefix */ + b = peek_next(insn_byte_t, insn); + attr = inat_get_opcode_attribute(b); + if (inat_is_vex_prefix(attr)) { + insn_byte_t b2 = peek_nbyte_next(insn_byte_t, insn, 1); + if (!insn->x86_64) { + /* + * In 32-bits mode, if the [7:6] bits (mod bits of + * ModRM) on the second byte are not 11b, it is + * LDS or LES. + */ + if (X86_MODRM_MOD(b2) != 3) { + goto vex_end; + } + } + insn->vex_prefix.bytes[0] = b; + insn->vex_prefix.bytes[1] = b2; + if (inat_is_vex3_prefix(attr)) { + b2 = peek_nbyte_next(insn_byte_t, insn, 2); + insn->vex_prefix.bytes[2] = b2; + insn->vex_prefix.nbytes = 3; + insn->next_byte += 3; + if (insn->x86_64 && X86_VEX_W(b2)) { + /* VEX.W overrides opnd_size */ + insn->opnd_bytes = 8; + } + } else { + insn->vex_prefix.nbytes = 2; + insn->next_byte += 2; + } + } vex_end: - insn->vex_prefix.got = 1; + insn->vex_prefix.got = 1; - prefixes->got = 1; + prefixes->got = 1; err_out: - return; + return; } /** * insn_get_opcode - collect opcode(s) - * @insn: &struct insn containing instruction + * @insn: &struct insn containing instruction * * Populates @insn->opcode, updates @insn->next_byte to point past the * opcode byte(s), and set @insn->attr (except for groups). @@ -187,50 +200,54 @@ err_out: */ void insn_get_opcode(struct insn *insn) { - struct insn_field *opcode = &insn->opcode; - insn_byte_t op; - int pfx_id; - if (opcode->got) - return; - if (!insn->prefixes.got) - insn_get_prefixes(insn); - - /* Get first opcode */ - op = get_next(insn_byte_t, insn); - opcode->bytes[0] = op; - opcode->nbytes = 1; - - /* Check if there is VEX prefix or not */ - if (insn_is_avx(insn)) { - insn_byte_t m, p; - m = insn_vex_m_bits(insn); - p = insn_vex_p_bits(insn); - insn->attr = inat_get_avx_attribute(op, m, p); - if (!inat_accept_vex(insn->attr) && !inat_is_group(insn->attr)) - insn->attr = 0; /* This instruction is bad */ - goto end; /* VEX has only 1 byte for opcode */ - } - - insn->attr = inat_get_opcode_attribute(op); - while (inat_is_escape(insn->attr)) { - /* Get escaped opcode */ - op = get_next(insn_byte_t, insn); - opcode->bytes[opcode->nbytes++] = op; - pfx_id = insn_last_prefix_id(insn); - insn->attr = inat_get_escape_attribute(op, pfx_id, insn->attr); - } - if (inat_must_vex(insn->attr)) - insn->attr = 0; /* This instruction is bad */ + struct insn_field *opcode = &insn->opcode; + insn_byte_t op; + int pfx_id; + + if (opcode->got) { + return; + } + if (!insn->prefixes.got) { + insn_get_prefixes(insn); + } + + /* Get first opcode */ + op = get_next(insn_byte_t, insn); + opcode->bytes[0] = op; + opcode->nbytes = 1; + + /* Check if there is VEX prefix or not */ + if (insn_is_avx(insn)) { + insn_byte_t m = insn_vex_m_bits(insn); + insn_byte_t p = insn_vex_p_bits(insn); + insn->attr = inat_get_avx_attribute(op, m, p); + if (!inat_accept_vex(insn->attr) && !inat_is_group(insn->attr)) { + insn->attr = 0; /* This instruction is bad */ + } + goto end; /* VEX has only 1 byte for opcode */ + } + + insn->attr = inat_get_opcode_attribute(op); + while (inat_is_escape(insn->attr)) { + /* Get escaped opcode */ + op = get_next(insn_byte_t, insn); + opcode->bytes[opcode->nbytes++] = op; + pfx_id = insn_last_prefix_id(insn); + insn->attr = inat_get_escape_attribute(op, pfx_id, insn->attr); + } + if (inat_must_vex(insn->attr)) { + insn->attr = 0; /* This instruction is bad */ + } end: - opcode->got = 1; + opcode->got = 1; err_out: - return; + return; } /** * insn_get_modrm - collect ModRM byte, if any - * @insn: &struct insn containing instruction + * @insn: &struct insn containing instruction * * Populates @insn->modrm and updates @insn->next_byte to point past the * ModRM byte, if any. If necessary, first collects the preceding bytes @@ -238,90 +255,98 @@ err_out: */ void insn_get_modrm(struct insn *insn) { - struct insn_field *modrm = &insn->modrm; - insn_byte_t pfx_id, mod; - if (modrm->got) - return; - if (!insn->opcode.got) - insn_get_opcode(insn); - - if (inat_has_modrm(insn->attr)) { - mod = get_next(insn_byte_t, insn); - modrm->value = mod; - modrm->nbytes = 1; - if (inat_is_group(insn->attr)) { - pfx_id = (insn_byte_t)insn_last_prefix_id(insn); - insn->attr = inat_get_group_attribute(mod, pfx_id, - insn->attr); - if (insn_is_avx(insn) && !inat_accept_vex(insn->attr)) - insn->attr = 0; /* This is bad */ - } - } - - if (insn->x86_64 && inat_is_force64(insn->attr)) - insn->opnd_bytes = 8; - modrm->got = 1; + struct insn_field *modrm = &insn->modrm; + insn_byte_t pfx_id; + insn_byte_t mod; + + if (modrm->got) { + return; + } + if (!insn->opcode.got) { + insn_get_opcode(insn); + } + + if (inat_has_modrm(insn->attr)) { + mod = get_next(insn_byte_t, insn); + modrm->value = mod; + modrm->nbytes = 1; + if (inat_is_group(insn->attr)) { + pfx_id = (insn_byte_t)insn_last_prefix_id(insn); + insn->attr = inat_get_group_attribute(mod, pfx_id, insn->attr); + if (insn_is_avx(insn) && !inat_accept_vex(insn->attr)) { + insn_get_opcode(insn); + } + } + } + + if (insn->x86_64 && inat_is_force64(insn->attr)) { + insn->opnd_bytes = 8; + } + modrm->got = 1; err_out: - return; + return; } /** * insn_rip_relative() - Does instruction use RIP-relative addressing mode? - * @insn: &struct insn containing instruction + * @insn: &struct insn containing instruction * * If necessary, first collects the instruction up to and including the * ModRM byte. No effect if @insn->x86_64 is 0. */ int insn_rip_relative(struct insn *insn) { - struct insn_field *modrm = &insn->modrm; - - if (!insn->x86_64) - return 0; - if (!modrm->got) - insn_get_modrm(insn); - /* - * For rip-relative instructions, the mod field (top 2 bits) - * is zero and the r/m field (bottom 3 bits) is 0x5. - */ - return (modrm->nbytes && (modrm->value & 0xc7) == 0x5); + struct insn_field *modrm = &insn->modrm; + + if (!insn->x86_64) { + return 0; + } + if (!modrm->got) { + insn_get_modrm(insn); + } + /* + * For rip-relative instructions, the mod field (top 2 bits) + * is zero and the r/m field (bottom 3 bits) is 0x5. + */ + return (modrm->nbytes && (modrm->value & 0xc7) == 0x5); } /** * insn_get_sib() - Get the SIB byte of instruction - * @insn: &struct insn containing instruction + * @insn: &struct insn containing instruction * * If necessary, first collects the instruction up to and including the * ModRM byte. */ void insn_get_sib(struct insn *insn) { - insn_byte_t modrm; - - if (insn->sib.got) - return; - if (!insn->modrm.got) - insn_get_modrm(insn); - if (insn->modrm.nbytes) { - modrm = (insn_byte_t)insn->modrm.value; - if (insn->addr_bytes != 2 && - X86_MODRM_MOD(modrm) != 3 && X86_MODRM_RM(modrm) == 4) { - insn->sib.value = get_next(insn_byte_t, insn); - insn->sib.nbytes = 1; - } - } - insn->sib.got = 1; + insn_byte_t modrm; + + if (insn->sib.got) { + return; + } + if (!insn->modrm.got) { + insn_get_modrm(insn); + } + if (insn->modrm.nbytes) { + modrm = (insn_byte_t)insn->modrm.value; + if (insn->addr_bytes != 2 && + X86_MODRM_MOD(modrm) != 3 && X86_MODRM_RM(modrm) == 4) { + insn->sib.value = get_next(insn_byte_t, insn); + insn->sib.nbytes = 1; + } + } + insn->sib.got = 1; err_out: - return; + return; } - /** * insn_get_displacement() - Get the displacement of instruction - * @insn: &struct insn containing instruction + * @insn: &struct insn containing instruction * * If necessary, first collects the instruction up to and including the * SIB byte. @@ -329,169 +354,176 @@ err_out: */ void insn_get_displacement(struct insn *insn) { - insn_byte_t mod, rm, base; - - if (insn->displacement.got) - return; - if (!insn->sib.got) - insn_get_sib(insn); - if (insn->modrm.nbytes) { - /* - * Interpreting the modrm byte: - * mod = 00 - no displacement fields (exceptions below) - * mod = 01 - 1-byte displacement field - * mod = 10 - displacement field is 4 bytes, or 2 bytes if - * address size = 2 (0x67 prefix in 32-bit mode) - * mod = 11 - no memory operand - * - * If address size = 2... - * mod = 00, r/m = 110 - displacement field is 2 bytes - * - * If address size != 2... - * mod != 11, r/m = 100 - SIB byte exists - * mod = 00, SIB base = 101 - displacement field is 4 bytes - * mod = 00, r/m = 101 - rip-relative addressing, displacement - * field is 4 bytes - */ - mod = X86_MODRM_MOD(insn->modrm.value); - rm = X86_MODRM_RM(insn->modrm.value); - base = X86_SIB_BASE(insn->sib.value); - if (mod == 3) - goto out; - if (mod == 1) { - insn->displacement.value = get_next(char, insn); - insn->displacement.nbytes = 1; - } else if (insn->addr_bytes == 2) { - if ((mod == 0 && rm == 6) || mod == 2) { - insn->displacement.value = - get_next(short, insn); - insn->displacement.nbytes = 2; - } - } else { - if ((mod == 0 && rm == 5) || mod == 2 || - (mod == 0 && base == 5)) { - insn->displacement.value = get_next(int, insn); - insn->displacement.nbytes = 4; - } - } - } + insn_byte_t mod; + insn_byte_t rm; + insn_byte_t base; + + if (insn->displacement.got) { + return; + } + if (!insn->sib.got) { + insn_get_sib(insn); + } + if (insn->modrm.nbytes) { + /* + * Interpreting the modrm byte: + * mod = 00 - no displacement fields (exceptions below) + * mod = 01 - 1-byte displacement field + * mod = 10 - displacement field is 4 bytes, or 2 bytes if + * address size = 2 (0x67 prefix in 32-bit mode) + * mod = 11 - no memory operand + * + * If address size = 2... + * mod = 00, r/m = 110 - displacement field is 2 bytes + * + * If address size != 2... + * mod != 11, r/m = 100 - SIB byte exists + * mod = 00, SIB base = 101 - displacement field is 4 bytes + * mod = 00, r/m = 101 - rip-relative addressing, displacement + * field is 4 bytes + */ + mod = X86_MODRM_MOD(insn->modrm.value); + rm = X86_MODRM_RM(insn->modrm.value); + base = X86_SIB_BASE(insn->sib.value); + if (mod == 3) { + goto out; + } + if (mod == 1) { + insn->displacement.value = get_next(char, insn); + insn->displacement.nbytes = 1; + } else if (insn->addr_bytes == 2) { + if ((mod == 0 && rm == 6) || mod == 2) { + insn->displacement.value = + get_next(short, insn); + insn->displacement.nbytes = 2; + } + } else { + if ((mod == 0 && rm == 5) || mod == 2 || + (mod == 0 && base == 5)) { + insn->displacement.value = get_next(int, insn); + insn->displacement.nbytes = 4; + } + } + } out: - insn->displacement.got = 1; + insn->displacement.got = 1; err_out: - return; + return; } /* Decode moffset16/32/64. Return 0 if failed */ -static int __get_moffset(struct insn *insn) +static int get_moffset(struct insn *insn) { - switch (insn->addr_bytes) { - case 2: - insn->moffset1.value = get_next(short, insn); - insn->moffset1.nbytes = 2; - break; - case 4: - insn->moffset1.value = get_next(int, insn); - insn->moffset1.nbytes = 4; - break; - case 8: - insn->moffset1.value = get_next(int, insn); - insn->moffset1.nbytes = 4; - insn->moffset2.value = get_next(int, insn); - insn->moffset2.nbytes = 4; - break; - default: /* opnd_bytes must be modified manually */ - goto err_out; - } - insn->moffset1.got = insn->moffset2.got = 1; - - return 1; + switch (insn->addr_bytes) { + case 2: + insn->moffset1.value = get_next(short, insn); + insn->moffset1.nbytes = 2; + break; + case 4: + insn->moffset1.value = get_next(int, insn); + insn->moffset1.nbytes = 4; + break; + case 8: + insn->moffset1.value = get_next(int, insn); + insn->moffset1.nbytes = 4; + insn->moffset2.value = get_next(int, insn); + insn->moffset2.nbytes = 4; + break; + default: /* opnd_bytes must be modified manually */ + goto err_out; + } + insn->moffset1.got = insn->moffset2.got = 1; + + return 1; err_out: - return 0; + return 0; } /* Decode imm v32(Iz). Return 0 if failed */ -static int __get_immv32(struct insn *insn) +static int get_immv32(struct insn *insn) { - switch (insn->opnd_bytes) { - case 2: - insn->immediate.value = get_next(short, insn); - insn->immediate.nbytes = 2; - break; - case 4: - case 8: - insn->immediate.value = get_next(int, insn); - insn->immediate.nbytes = 4; - break; - default: /* opnd_bytes must be modified manually */ - goto err_out; - } - - return 1; + switch (insn->opnd_bytes) { + case 2: + insn->immediate.value = get_next(short, insn); + insn->immediate.nbytes = 2; + break; + case 4: + case 8: + insn->immediate.value = get_next(int, insn); + insn->immediate.nbytes = 4; + break; + default: /* opnd_bytes must be modified manually */ + goto err_out; + } + + return 1; err_out: - return 0; + return 0; } /* Decode imm v64(Iv/Ov), Return 0 if failed */ -static int __get_immv(struct insn *insn) +static int get_immv(struct insn *insn) { - switch (insn->opnd_bytes) { - case 2: - insn->immediate1.value = get_next(short, insn); - insn->immediate1.nbytes = 2; - break; - case 4: - insn->immediate1.value = get_next(int, insn); - insn->immediate1.nbytes = 4; - break; - case 8: - insn->immediate1.value = get_next(int, insn); - insn->immediate1.nbytes = 4; - insn->immediate2.value = get_next(int, insn); - insn->immediate2.nbytes = 4; - break; - default: /* opnd_bytes must be modified manually */ - goto err_out; - } - insn->immediate1.got = insn->immediate2.got = 1; - - return 1; + switch (insn->opnd_bytes) { + case 2: + insn->immediate1.value = get_next(short, insn); + insn->immediate1.nbytes = 2; + break; + case 4: + insn->immediate1.value = get_next(int, insn); + insn->immediate1.nbytes = 4; + break; + case 8: + insn->immediate1.value = get_next(int, insn); + insn->immediate1.nbytes = 4; + insn->immediate2.value = get_next(int, insn); + insn->immediate2.nbytes = 4; + break; + default: /* opnd_bytes must be modified manually */ + goto err_out; + } + insn->immediate1.got = insn->immediate2.got = 1; + + return 1; + err_out: - return 0; + return 0; } /* Decode ptr16:16/32(Ap) */ -static int __get_immptr(struct insn *insn) +static int get_immptr(struct insn *insn) { - switch (insn->opnd_bytes) { - case 2: - insn->immediate1.value = get_next(short, insn); - insn->immediate1.nbytes = 2; - break; - case 4: - insn->immediate1.value = get_next(int, insn); - insn->immediate1.nbytes = 4; - break; - case 8: - /* ptr16:64 is not exist (no segment) */ - return 0; - default: /* opnd_bytes must be modified manually */ - goto err_out; - } - insn->immediate2.value = get_next(unsigned short, insn); - insn->immediate2.nbytes = 2; - insn->immediate1.got = insn->immediate2.got = 1; - - return 1; + switch (insn->opnd_bytes) { + case 2: + insn->immediate1.value = get_next(short, insn); + insn->immediate1.nbytes = 2; + break; + case 4: + insn->immediate1.value = get_next(int, insn); + insn->immediate1.nbytes = 4; + break; + case 8: + /* ptr16:64 is not exist (no segment) */ + return 0; + default: /* opnd_bytes must be modified manually */ + goto err_out; + } + insn->immediate2.value = get_next(unsigned short, insn); + insn->immediate2.nbytes = 2; + insn->immediate1.got = insn->immediate2.got = 1; + + return 1; + err_out: - return 0; + return 0; } /** * insn_get_immediate() - Get the immediates of instruction - * @insn: &struct insn containing instruction + * @insn: &struct insn containing instruction * * If necessary, first collects the instruction up to and including the * displacement bytes. @@ -500,80 +532,89 @@ err_out: */ void insn_get_immediate(struct insn *insn) { - if (insn->immediate.got) - return; - if (!insn->displacement.got) - insn_get_displacement(insn); - - if (inat_has_moffset(insn->attr)) { - if (!__get_moffset(insn)) - goto err_out; - goto done; - } - - if (!inat_has_immediate(insn->attr)) - /* no immediates */ - goto done; - - switch (inat_immediate_size(insn->attr)) { - case INAT_IMM_BYTE: - insn->immediate.value = get_next(char, insn); - insn->immediate.nbytes = 1; - break; - case INAT_IMM_WORD: - insn->immediate.value = get_next(short, insn); - insn->immediate.nbytes = 2; - break; - case INAT_IMM_DWORD: - insn->immediate.value = get_next(int, insn); - insn->immediate.nbytes = 4; - break; - case INAT_IMM_QWORD: - insn->immediate1.value = get_next(int, insn); - insn->immediate1.nbytes = 4; - insn->immediate2.value = get_next(int, insn); - insn->immediate2.nbytes = 4; - break; - case INAT_IMM_PTR: - if (!__get_immptr(insn)) - goto err_out; - break; - case INAT_IMM_VWORD32: - if (!__get_immv32(insn)) - goto err_out; - break; - case INAT_IMM_VWORD: - if (!__get_immv(insn)) - goto err_out; - break; - default: - /* Here, insn must have an immediate, but failed */ - goto err_out; - } - if (inat_has_second_immediate(insn->attr)) { - insn->immediate2.value = get_next(char, insn); - insn->immediate2.nbytes = 1; - } + if (insn->immediate.got) { + return; + } + if (!insn->displacement.got) { + insn_get_displacement(insn); + } + + if (inat_has_moffset(insn->attr)) { + if (!get_moffset(insn)) { + goto err_out; + } + goto done; + } + + if (!inat_has_immediate(insn->attr)) { + /* no immediates */ + goto done; + } + + switch (inat_immediate_size(insn->attr)) { + case INAT_IMM_BYTE: + insn->immediate.value = get_next(char, insn); + insn->immediate.nbytes = 1; + break; + case INAT_IMM_WORD: + insn->immediate.value = get_next(short, insn); + insn->immediate.nbytes = 2; + break; + case INAT_IMM_DWORD: + insn->immediate.value = get_next(int, insn); + insn->immediate.nbytes = 4; + break; + case INAT_IMM_QWORD: + insn->immediate1.value = get_next(int, insn); + insn->immediate1.nbytes = 4; + insn->immediate2.value = get_next(int, insn); + insn->immediate2.nbytes = 4; + break; + case INAT_IMM_PTR: + if (!get_immptr(insn)) { + goto err_out; + } + break; + case INAT_IMM_VWORD32: + if (!get_immv32(insn)) { + goto err_out; + } + break; + case INAT_IMM_VWORD: + if (!get_immv(insn)) { + goto err_out; + } + break; + default: + /* Here, insn must have an immediate, but failed */ + goto err_out; + } + if (inat_has_second_immediate(insn->attr)) { + insn->immediate2.value = get_next(char, insn); + insn->immediate2.nbytes = 1; + } done: - insn->immediate.got = 1; + insn->immediate.got = 1; err_out: - return; + return; } /** * insn_get_length() - Get the length of instruction - * @insn: &struct insn containing instruction + * @insn: &struct insn containing instruction * * If necessary, first collects the instruction up to and including the * immediates bytes. */ void insn_get_length(struct insn *insn) { - if (insn->length) - return; - if (!insn->immediate.got) - insn_get_immediate(insn); - insn->length = (unsigned char)((unsigned long)insn->next_byte - - (unsigned long)insn->kaddr); + if (insn->length) { + return; + } + if (!insn->immediate.got) { + insn_get_immediate(insn); + } + insn->length = (unsigned char)((unsigned long)insn->next_byte - + (unsigned long)insn->kaddr); } diff --git a/upatch-diff/list.h b/upatch-diff/list.h index b3b28e15..b56a2b03 100644 --- a/upatch-diff/list.h +++ b/upatch-diff/list.h @@ -33,8 +33,8 @@ * under normal circumstances, used to verify that nobody uses * non-initialized list entries. */ -#define LIST_POISON1 ((void *) 0x00100100) -#define LIST_POISON2 ((void *) 0x00200200) +#define LIST_POISON1 ((void *) 0x00100100) +#define LIST_POISON2 ((void *) 0x00200200) /** * Get offset of a member @@ -48,9 +48,10 @@ * @param member the name of the member within the struct. * */ -#define container_of(ptr, type, member) ({ \ - typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) +#define container_of(ptr, type, member) ({ \ + typeof(((type *)0)->member) *__mptr = (ptr); \ + (type *)((char *)__mptr - offsetof(type, member)); \ +}) /** * Simple doubly linked list implementation. @@ -62,67 +63,66 @@ * using the generic single-entry routines. */ struct list_head { - struct list_head *next, *prev; + struct list_head *next, *prev; }; #define LIST_HEAD_INIT(name) { &(name), &(name) } #define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) + struct list_head name = LIST_HEAD_INIT(name) #define INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ } while (0) #define list_entry(ptr, type, member) \ - container_of(ptr, type, member) + container_of(ptr, type, member) /** * list_next_entry - get the next element in list - * @pos: the type * to cursor - * @member: the name of the list_struct within the struct. + * @pos: the type * to cursor + * @member: the name of the list_struct within the struct. */ #define list_next_entry(pos, member) \ - list_entry((pos)->member.next, typeof(*(pos)), member) + list_entry((pos)->member.next, typeof(*(pos)), member) /** - * list_for_each_entry - iterate over list of given type - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. */ -#define list_for_each_entry(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member)) +#define list_for_each_entry(pos, head, member) \ + for ((pos) = list_entry((head)->next, typeof(*(pos)), member); \ + &((pos)->member) != (head); \ + (pos) = list_entry((pos)->member.next, typeof(*(pos)), member)) /** * list_for_each_entry_continue - continue iteration over list of given type - * @pos: the type * to use as a loop cursor. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. * * Continue to iterate over list of given type, continuing after * the current position. */ -#define list_for_each_entry_continue(pos, head, member) \ - for (pos = list_next_entry(pos, member); \ - &pos->member != (head); \ - pos = list_next_entry(pos, member)) +#define list_for_each_entry_continue(pos, head, member) \ + for ((pos) = list_next_entry(pos, member); \ + &((pos)->member) != (head); \ + (pos) = list_next_entry(pos, member)) /** * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @pos: the type * to use as a loop counter. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. */ -#define list_for_each_entry_safe(pos, n, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - n = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, typeof(*n), member)) - +#define list_for_each_entry_safe(pos, n, head, member) \ + for ((pos) = list_entry((head)->next, typeof(*(pos)), member), \ + (n) = list_entry((pos)->member.next, typeof(*(pos)), member); \ + &((pos)->member) != (head); \ + (pos) = (n), (n) = list_entry((n)->member.next, typeof(*(n)), member)) /* * Insert a new entry between two known consecutive entries. @@ -130,14 +130,12 @@ struct list_head { * This is only for internal list manipulation where we know * the prev/next entries already! */ -static inline void __list_add(struct list_head *new, - struct list_head *prev, - struct list_head *next) +static inline void list_insert(struct list_head *new, struct list_head *prev, struct list_head *next) { - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; } /** @@ -150,7 +148,7 @@ static inline void __list_add(struct list_head *new, */ static inline void list_add(struct list_head *new, struct list_head *head) { - __list_add(new, head, head->next); + list_insert(new, head, head->next); } /** @@ -163,7 +161,7 @@ static inline void list_add(struct list_head *new, struct list_head *head) */ static inline void list_add_tail(struct list_head *new, struct list_head *head) { - __list_add(new, head->prev, head); + list_insert(new, head->prev, head); } @@ -174,10 +172,10 @@ static inline void list_add_tail(struct list_head *new, struct list_head *head) * This is only for internal list manipulation where we know * the prev/next entries already! */ -static inline void __list_del(struct list_head * prev, struct list_head * next) +static inline void list_remove(struct list_head * prev, struct list_head * next) { - next->prev = prev; - prev->next = next; + next->prev = prev; + prev->next = next; } /** @@ -188,9 +186,9 @@ static inline void __list_del(struct list_head * prev, struct list_head * next) */ static inline void list_del(struct list_head *entry) { - __list_del(entry->prev, entry->next); - entry->next = LIST_POISON1; - entry->prev = LIST_POISON2; + list_remove(entry->prev, entry->next); + entry->next = LIST_POISON1; + entry->prev = LIST_POISON2; } /** @@ -200,13 +198,12 @@ static inline void list_del(struct list_head *entry) * * If @old was empty, it will be overwritten. */ -static inline void list_replace(struct list_head *old, - struct list_head *new) +static inline void list_replace(struct list_head *old, struct list_head *new) { - new->next = old->next; - new->next->prev = new; - new->prev = old->prev; - new->prev->next = new; + new->next = old->next; + new->next->prev = new; + new->prev = old->prev; + new->prev->next = new; } -#endif \ No newline at end of file +#endif diff --git a/upatch-diff/log.h b/upatch-diff/log.h index 34b58bfa..a109958b 100644 --- a/upatch-diff/log.h +++ b/upatch-diff/log.h @@ -29,43 +29,45 @@ #include /* Files that include log.h must define g_loglevel and g_logprefix */ -extern enum LogLevel g_loglevel; +extern enum log_level g_loglevel; extern char *g_logprefix; -enum exit_status{ - EXIT_STATUS_SUCCESS = 0, - EXIT_STATUS_ERROR = 1, - EXIT_STATUS_DIFF_FATAL = 2, - EXIT_STATUS_NO_CHANGE = 3, +enum exit_status { + EXIT_STATUS_SUCCESS = 0, + EXIT_STATUS_ERROR = 1, }; /* Since upatch-build is an one-shot program, we do not care about failure handler */ #define ERROR(format, ...) \ - error(EXIT_STATUS_ERROR, 0, "ERROR: %s: %s: %d: " format, g_logprefix, __FUNCTION__, __LINE__, ##__VA_ARGS__) - -#define DIFF_FATAL(format, ...) \ - error(EXIT_STATUS_DIFF_FATAL, 0, "ERROR: %s: %s: %d: " format, g_logprefix, __FUNCTION__, __LINE__, ##__VA_ARGS__) + error(EXIT_STATUS_ERROR, 0, "ERROR: %s: %s: %d: " format, \ + g_logprefix, __FUNCTION__, __LINE__, ##__VA_ARGS__) /* it is time cost */ #define log_debug(format, ...) log(DEBUG, format, ##__VA_ARGS__) -#define log_normal(format, ...) log(NORMAL, "%s: " format, g_logprefix, ##__VA_ARGS__) -#define log_warn(format, ...) log(WARN, "%s: " format, g_logprefix, ##__VA_ARGS__) +#define log_normal(format, ...) log(NORMAL, format, ##__VA_ARGS__) +#define log_warn(format, ...) log(WARN, format, ##__VA_ARGS__) +#define log_error(format, ...) log(ERR, format, ##__VA_ARGS__) #define log(level, format, ...) \ -({ \ - if (g_loglevel <= (level)) \ - printf(format, ##__VA_ARGS__); \ -}) + do { \ + if (g_loglevel <= (level)) { \ + printf(format, ##__VA_ARGS__); \ + } \ + } while (0) #define REQUIRE(COND, message) \ - do \ - if (!(COND)) \ - ERROR(message); \ - while (0) + do { \ + if (!(COND)) { \ + ERROR(message); \ + } \ + } \ + while (0) -enum LogLevel { - DEBUG, - NORMAL, +enum log_level { + DEBUG, + NORMAL, WARN, + ERR, }; -#endif \ No newline at end of file + +#endif diff --git a/upatch-diff/running-elf.c b/upatch-diff/running-elf.c index c99b3958..d9c1d6fa 100644 --- a/upatch-diff/running-elf.c +++ b/upatch-diff/running-elf.c @@ -35,7 +35,8 @@ #include "running-elf.h" #include "log.h" -/* TODO: need to judge whether running_elf is a Position-Independent Executable file +/* TODO: + * need to judge whether running_elf is a Position-Independent Executable file * https://github.com/bminor/binutils-gdb/blob/master/binutils/readelf.c */ static bool is_pie(void) @@ -47,9 +48,9 @@ static bool is_exec(struct Elf *elf) { GElf_Ehdr ehdr; - if (!gelf_getehdr(elf, &ehdr)) + if (!gelf_getehdr(elf, &ehdr)) { ERROR("gelf_getehdr running_file failed for %s.", elf_errmsg(0)); - + } return ehdr.e_type == ET_EXEC || (ehdr.e_type == ET_DYN && is_pie()); } @@ -61,38 +62,46 @@ void relf_init(char *elf_name, struct running_elf *relf) GElf_Sym sym; relf->fd = open(elf_name, O_RDONLY); - if (relf->fd == -1) + if (relf->fd == -1) { ERROR("open with errno = %d", errno); + } relf->elf = elf_begin(relf->fd, ELF_C_READ, NULL); - if (!relf->elf) + if (!relf->elf) { ERROR("elf_begin with error %s", elf_errmsg(0)); + } relf->is_exec = is_exec(relf->elf); while ((scn = elf_nextscn(relf->elf, scn)) != NULL) { - if (!gelf_getshdr(scn, &shdr)) + if (!gelf_getshdr(scn, &shdr)) { ERROR("gelf_getshdr with error %s", elf_errmsg(0)); - - if (shdr.sh_type == SHT_SYMTAB) + } + if (shdr.sh_type == SHT_SYMTAB) { break; + } } data = elf_getdata(scn, NULL); - if (!data) + if (!data) { ERROR("elf_getdata with error %s", elf_errmsg(0)); + } relf->obj_nr = (int)(shdr.sh_size / shdr.sh_entsize); relf->obj_syms = calloc((size_t)relf->obj_nr, sizeof(struct debug_symbol)); - if (!relf->obj_syms) + if (!relf->obj_syms) { ERROR("calloc with errno = %d", errno); + } - for (int i = 0; i < relf->obj_nr; i ++) { - if (!gelf_getsym(data, i, &sym)) + for (int i = 0; i < relf->obj_nr; i++) { + if (!gelf_getsym(data, i, &sym)) { ERROR("gelf_getsym with error %s", elf_errmsg(0)); - relf->obj_syms[i].name = elf_strptr(relf->elf, shdr.sh_link, sym.st_name); - if (!relf->obj_syms[i].name) + } + relf->obj_syms[i].name = elf_strptr(relf->elf, + shdr.sh_link, sym.st_name); + if (!relf->obj_syms[i].name) { ERROR("elf_strptr with error %s", elf_errmsg(0)); + } relf->obj_syms[i].type = GELF_ST_TYPE(sym.st_info); relf->obj_syms[i].bind = GELF_ST_BIND(sym.st_info); relf->obj_syms[i].shndx = sym.st_shndx; @@ -112,8 +121,8 @@ int relf_close(struct running_elf *relf) return 0; } -bool lookup_relf(struct running_elf *relf, - struct symbol *lookup_sym, struct lookup_result *result) +bool lookup_relf(struct running_elf *relf, struct symbol *lookup_sym, + struct lookup_result *result) { struct debug_symbol *symbol = NULL; unsigned long sympos = 0; @@ -128,7 +137,6 @@ bool lookup_relf(struct running_elf *relf, if (result->symbol != NULL && symbol->type == STT_FILE) { break; } - if (strcmp(symbol->name, lookup_sym->name) != 0 || symbol->bind != lookup_sym->bind) { continue; diff --git a/upatch-diff/running-elf.h b/upatch-diff/running-elf.h index b02c8e2b..cdf61d1d 100644 --- a/upatch-diff/running-elf.h +++ b/upatch-diff/running-elf.h @@ -36,8 +36,8 @@ struct symbol; struct lookup_result { struct debug_symbol *symbol; - unsigned long sympos; - bool global; + unsigned long sympos; + bool global; }; struct debug_symbol { @@ -62,4 +62,4 @@ int relf_close(struct running_elf *); bool lookup_relf(struct running_elf *, struct symbol *, struct lookup_result *); -#endif \ No newline at end of file +#endif diff --git a/upatch-diff/upatch-dynrela.h b/upatch-diff/upatch-dynrela.h index 7d10378a..d31c9f0b 100644 --- a/upatch-diff/upatch-dynrela.h +++ b/upatch-diff/upatch-dynrela.h @@ -37,4 +37,4 @@ struct upatch_relocation { struct upatch_symbol *sym; }; -#endif /* __UPATCH_DYN_RELA_H_ */ \ No newline at end of file +#endif /* __UPATCH_DYN_RELA_H_ */ diff --git a/upatch-diff/upatch-elf.c b/upatch-diff/upatch-elf.c index 171e88eb..a51f0080 100644 --- a/upatch-diff/upatch-elf.c +++ b/upatch-diff/upatch-elf.c @@ -40,36 +40,43 @@ static void create_section_list(struct upatch_elf *uelf) { - size_t shstrndx, sections_nr; + size_t shstrndx; + size_t sections_nr; struct section *sec; Elf_Scn *scn = NULL; - if (elf_getshdrnum(uelf->elf, §ions_nr)) + if (elf_getshdrnum(uelf->elf, §ions_nr)) { ERROR("elf_getshdrnum with error %s", elf_errmsg(0)); + } - sections_nr --; + sections_nr--; - if (elf_getshdrstrndx(uelf->elf, &shstrndx)) + if (elf_getshdrstrndx(uelf->elf, &shstrndx)) { ERROR("elf_getshdrstrndx with error %s", elf_errmsg(0)); + } - log_debug("=== section list (%zu) === \n", sections_nr); - while (sections_nr --) { + log_debug("=== section list (%zu) ===\n", sections_nr); + while (sections_nr--) { ALLOC_LINK(sec, &uelf->sections); scn = elf_nextscn(uelf->elf, scn); - if (!scn) + if (!scn) { ERROR("elf_nextscn with error %s", elf_errmsg(0)); - - if (!gelf_getshdr(scn, &sec->sh)) + } + if (!gelf_getshdr(scn, &sec->sh)) { ERROR("gelf_getshdr with error %s", elf_errmsg(0)); + } sec->name = elf_strptr(uelf->elf, shstrndx, sec->sh.sh_name); - if (!sec->name) + if (!sec->name) { ERROR("elf_strptr with error %s", elf_errmsg(0)); + } + sec->data = elf_getdata(scn, NULL); - if (!sec->data) + if (!sec->data) { ERROR("elf_getdata with error %s", elf_errmsg(0)); + } sec->name_source = DATA_SOURCE_ELF; sec->data_source = DATA_SOURCE_ELF; @@ -77,46 +84,52 @@ static void create_section_list(struct upatch_elf *uelf) sec->index = (unsigned int)elf_ndxscn(scn); /* found extended section header */ - if (sec->sh.sh_type == SHT_SYMTAB_SHNDX) + if (sec->sh.sh_type == SHT_SYMTAB_SHNDX) { uelf->symtab_shndx = sec->data; /* correct ? */ + } log_debug("ndx %02d, data %p, size %zu, name %s\n", sec->index, sec->data->d_buf, sec->data->d_size, sec->name); } - if (elf_nextscn(uelf->elf, scn)) + if (elf_nextscn(uelf->elf, scn)) { ERROR("elf_nextscn with error %s", elf_errmsg(0)); + } } static void create_symbol_list(struct upatch_elf *uelf) { struct section *symtab; - unsigned int symbols_nr; Elf32_Word shndx; - struct symbol *sym; + + unsigned int symbols_nr; unsigned int index = 0; + struct symbol *sym; /* consider type first */ symtab = find_section_by_name(&uelf->sections, ".symtab"); - if (!symtab) + if (!symtab) { ERROR("can't find symbol table"); + } symbols_nr = (unsigned int)(symtab->sh.sh_size / symtab->sh.sh_entsize); log_debug("\n=== symbol list (%d entries) ===\n", symbols_nr); - while (symbols_nr --) { + while (symbols_nr--) { ALLOC_LINK(sym, &uelf->symbols); INIT_LIST_HEAD(&sym->children); sym->index = index; - if (!gelf_getsym(symtab->data, (int)index, &sym->sym)) + if (!gelf_getsym(symtab->data, (int)index, &sym->sym)) { ERROR("gelf_getsym with error %s", elf_errmsg(0)); + } - index ++; + index++; sym->name = elf_strptr(uelf->elf, symtab->sh.sh_link, sym->sym.st_name); - if (!sym->name) + if (!sym->name) { ERROR("elf_strptr with error %s", elf_errmsg(0)); + } sym->type = GELF_ST_TYPE(sym->sym.st_info); sym->bind = GELF_ST_BIND(sym->sym.st_info); @@ -125,70 +138,74 @@ static void create_symbol_list(struct upatch_elf *uelf) /* releated section located in extended header */ if (shndx == SHN_XINDEX && !gelf_getsymshndx(symtab->data, uelf->symtab_shndx, - (int)sym->index, &sym->sym, &shndx)) + (int)sym->index, &sym->sym, &shndx)) { ERROR("gelf_getsymshndx with error %s", elf_errmsg(0)); - - if ((sym->sym.st_shndx > SHN_UNDEF && sym->sym.st_shndx < SHN_LORESERVE) || - sym->sym.st_shndx == SHN_XINDEX) { - + } + if (sym->sym.st_shndx == SHN_XINDEX || + (sym->sym.st_shndx > SHN_UNDEF && + sym->sym.st_shndx < SHN_LORESERVE)) { sym->sec = find_section_by_index(&uelf->sections, shndx); - if (!sym->sec) - ERROR("no releated section found for symbol %s \n", sym->name); + if (!sym->sec) { + ERROR("no releated section found for symbol %s\n", sym->name); + } /* this symbol is releated with a section */ if (sym->type == STT_SECTION) { /* secsym must be the bundleable symbol */ sym->sec->secsym = sym; - /* use section name as symbol name */ sym->name = sym->sec->name; } } log_debug("sym %02d, type %d, bind %d, ndx %02d, name %s", - sym->index, sym->type, sym->bind, sym->sym.st_shndx, - sym->name); - if (sym->sec) + sym->index, sym->type, sym->bind, sym->sym.st_shndx, sym->name); + if (sym->sec) { log_debug(" -> %s", sym->sec->name); + } log_debug("\n"); } } static void create_rela_list(struct upatch_elf *uelf, struct section *relasec) { + struct rela *rela; unsigned long rela_nr; + unsigned int symndx; - struct rela *rela; - int index = 0, skip = 0; + int index = 0; + int skip = 0; INIT_LIST_HEAD(&relasec->relas); - /* for relocation sections, sh_info is the index which these informations apply */ + /* for relocation sections, sh_info is the index which these info apply */ relasec->base = find_section_by_index(&uelf->sections, relasec->sh.sh_info); - if (!relasec->base) + if (!relasec->base) { ERROR("no base section found for relocation section %s", relasec->name); + } relasec->base->rela = relasec; rela_nr = relasec->sh.sh_size / relasec->sh.sh_entsize; - log_debug("\n=== rela list for %s (%ld entries) === \n", + log_debug("\n=== rela list for %s (%ld entries) ===\n", relasec->base->name, rela_nr); if (is_debug_section(relasec)) { - log_debug("skipping rela listing for .debug_* section \n"); + log_debug("skipping rela listing for .debug_* section\n"); skip = 1; } if (is_note_section(relasec)) { - log_debug("skipping rela listing for .note_* section \n"); + log_debug("skipping rela listing for .note_* section\n"); skip = 1; } - while (rela_nr --) { + while (rela_nr--) { ALLOC_LINK(rela, &relasec->relas); /* use index because we need to keep the order of rela */ - if (!gelf_getrela(relasec->data, index, &rela->rela)) + if (!gelf_getrela(relasec->data, index, &rela->rela)) { ERROR("gelf_getrela with error %s", elf_errmsg(0)); + } index++; rela->type = GELF_R_TYPE(rela->rela.r_info); @@ -196,33 +213,39 @@ static void create_rela_list(struct upatch_elf *uelf, struct section *relasec) rela->offset = (unsigned int)rela->rela.r_offset; symndx = (unsigned int)GELF_R_SYM(rela->rela.r_info); rela->sym = find_symbol_by_index(&uelf->symbols, symndx); - if (!rela->sym) - ERROR("no rela entry symbol found \n"); + if (!rela->sym) { + ERROR("no rela entry symbol found\n"); + } if (rela->sym->sec && is_string_section(rela->sym->sec)) { rela->string = rela->sym->sec->data->d_buf + rela->sym->sym.st_value + rela_target_offset(uelf, relasec, rela); - if (!rela->string) + if (!rela->string) { ERROR("could not lookup rela string for %s+%ld", rela->sym->name, rela->addend); + } } - if (skip) + if (skip) { continue; + } log_debug("offset %ld, type %d, %s %s %ld", rela->offset, rela->type, rela->sym->name, (rela->addend < 0) ? "-" : "+", labs(rela->addend)); - if (rela->string) // rela->string is not utf8 + if (rela->string) { + // rela->string is not utf8 log_debug(" string = %s", rela->string); + } log_debug("\n"); } } static void destroy_rela_list(struct section *relasec) { - struct rela *rela = NULL, *saferela = NULL; + struct rela *rela = NULL; + struct rela *saferela = NULL; list_for_each_entry_safe(rela, saferela, &relasec->relas, list) { list_del(&rela->list); @@ -234,7 +257,8 @@ static void destroy_rela_list(struct section *relasec) static void destroy_section_list(struct upatch_elf *uelf) { - struct section *sec = NULL, *safesec = NULL; + struct section *sec = NULL; + struct section *safesec = NULL; list_for_each_entry_safe(sec, safesec, &uelf->sections, list) { if (sec->twin) { @@ -270,7 +294,8 @@ static void destroy_section_list(struct upatch_elf *uelf) static void destroy_symbol_list(struct upatch_elf *uelf) { - struct symbol *sym = NULL, *safesym = NULL; + struct symbol *sym = NULL; + struct symbol *safesym = NULL; list_for_each_entry_safe(sym, safesym, &uelf->symbols, list) { if (sym->twin) { @@ -286,7 +311,8 @@ static void destroy_symbol_list(struct upatch_elf *uelf) static void destroy_string_list(struct upatch_elf *uelf) { - struct string *str = NULL, *safestr = NULL; + struct string *str = NULL; + struct string *safestr = NULL; list_for_each_entry_safe(str, safestr, &uelf->strings, list) { list_del(&str->list); @@ -298,18 +324,22 @@ static void destroy_string_list(struct upatch_elf *uelf) void upatch_elf_open(struct upatch_elf *uelf, const char *name) { + int fd = 1; + + Elf *elf = NULL; + GElf_Ehdr ehdr; struct section *sec; - Elf *elf = NULL; - int fd = 1; fd = open(name, O_RDONLY); - if (fd == -1) - ERROR("open %s failed with errno %d \n", name, errno); + if (fd == -1) { + ERROR("open %s failed with errno %d\n", name, errno); + } elf = elf_begin(fd, ELF_C_RDWR, NULL); - if (!elf) - ERROR("open elf %s failed with error %s \n", name, elf_errmsg(0)); + if (!elf) { + ERROR("open elf %s failed with error %s\n", name, elf_errmsg(0)); + } memset(uelf, 0, sizeof(*uelf)); INIT_LIST_HEAD(&uelf->sections); @@ -319,27 +349,27 @@ void upatch_elf_open(struct upatch_elf *uelf, const char *name) uelf->elf = elf; uelf->fd = fd; - if (!gelf_getehdr(uelf->elf, &ehdr)) - ERROR("get file %s elf header failed with error %s \n", - name, elf_errmsg(0)); - - /* TODO: check ELF type here, we only handle object file */ - if (ehdr.e_type != ET_REL) - ERROR("only handles relocatable files \n"); + if (!gelf_getehdr(uelf->elf, &ehdr)) { + ERROR("get file %s elf header failed with error %s\n", name, + elf_errmsg(0)); + } + if (ehdr.e_type != ET_REL) { + ERROR("only handles relocatable files\n"); + } /* * Main problem here is stack check, for kernel, only x86 is support * Not sure how to handle userspace, but let us handle x86 first here */ switch (ehdr.e_machine) { - case EM_AARCH64: - uelf->arch = AARCH64; - break; - case EM_X86_64: - uelf->arch = X86_64; - break; - default: - ERROR("unsupported architecture here"); + case EM_AARCH64: + uelf->arch = AARCH64; + break; + case EM_X86_64: + uelf->arch = X86_64; + break; + default: + ERROR("unsupported architecture here"); } create_section_list(uelf); diff --git a/upatch-diff/upatch-elf.h b/upatch-diff/upatch-elf.h index 6c62c931..030feca6 100644 --- a/upatch-diff/upatch-elf.h +++ b/upatch-diff/upatch-elf.h @@ -40,102 +40,102 @@ struct rela; struct symbol; enum data_source { - DATA_SOURCE_ELF, - DATA_SOURCE_REF, - DATA_SOURCE_ALLOC, + DATA_SOURCE_ELF, + DATA_SOURCE_REF, + DATA_SOURCE_ALLOC, }; enum status { - NEW, - CHANGED, - SAME + NEW, + CHANGED, + SAME }; enum symbol_strip { - SYMBOL_DEFAULT, - SYMBOL_USED, - SYMBOL_STRIP, + SYMBOL_DEFAULT, + SYMBOL_USED, + SYMBOL_STRIP, }; struct string { - struct list_head list; - char *name; + struct list_head list; + char *name; }; struct section { - struct list_head list; - struct section *twin; - char *name; - Elf_Data *data; - enum data_source name_source; - enum data_source data_source; - enum data_source dbuf_source; - GElf_Shdr sh; - int ignore; - int include; - int grouped; - unsigned int index; - enum status status; - union { + struct list_head list; + struct section *twin; + char *name; + Elf_Data *data; + enum data_source name_source; + enum data_source data_source; + enum data_source dbuf_source; + GElf_Shdr sh; + int ignore; + int include; + int grouped; + unsigned int index; + enum status status; + union { // section with relocation information - struct { - struct section *base; - struct list_head relas; - }; + struct { + struct section *base; + struct list_head relas; + }; // other function or data section - struct { - struct section *rela; - struct symbol *sym; - struct symbol *secsym; - }; - }; + struct { + struct section *rela; + struct symbol *sym; + struct symbol *secsym; + }; + }; }; struct rela { - struct list_head list; - GElf_Rela rela; - struct symbol *sym; - unsigned int type; - unsigned long offset; - long addend; - char *string; - bool need_dynrela; + struct list_head list; + GElf_Rela rela; + struct symbol *sym; + unsigned int type; + unsigned long offset; + long addend; + char *string; + bool need_dynrela; }; struct symbol { - struct list_head list; - struct symbol *twin; - struct symbol *parent; - struct list_head children; - struct list_head subfunction_node; - struct section *sec; - GElf_Sym sym; - char *name; - enum data_source name_source; - struct debug_symbol *relf_sym; - unsigned int index; - unsigned char bind; - unsigned char type; - enum status status; - union { - int include; /* used in the patched elf */ - enum symbol_strip strip; /* used in the output elf */ - }; + struct list_head list; + struct symbol *twin; + struct symbol *parent; + struct list_head children; + struct list_head subfunction_node; + struct section *sec; + GElf_Sym sym; + char *name; + enum data_source name_source; + struct debug_symbol *relf_sym; + unsigned int index; + unsigned char bind; + unsigned char type; + enum status status; + union { + int include; /* used in the patched elf */ + enum symbol_strip strip; /* used in the output elf */ + }; }; enum architecture { - X86_64 = 0x1 << 0, - AARCH64 = 0x1 << 1, + X86_64 = 0x1 << 0, + AARCH64 = 0x1 << 1, }; struct upatch_elf { - Elf *elf; - enum architecture arch; - struct list_head sections; - struct list_head symbols; - struct list_head strings; - Elf_Data *symtab_shndx; - int fd; + Elf *elf; + enum architecture arch; + struct list_head sections; + struct list_head symbols; + struct list_head strings; + Elf_Data *symtab_shndx; + int fd; }; // init a upatch_elf from a path diff --git a/upatch-diff/upatch-patch.h b/upatch-diff/upatch-patch.h index 5e2abce5..ec0148fc 100644 --- a/upatch-diff/upatch-patch.h +++ b/upatch-diff/upatch-patch.h @@ -23,7 +23,7 @@ #ifndef __UPATCH_PATCH_H_ #define __UPATCH_PATCH_H_ -#define SYM_OTHER 0x40 +#define SYM_OTHER 0x40 struct upatch_patch_func { unsigned long new_addr; @@ -34,4 +34,4 @@ struct upatch_patch_func { char *name; }; -#endif /* __UPATCH_PATCH_H_ */ \ No newline at end of file +#endif /* __UPATCH_PATCH_H_ */ -- Gitee