ksplice-0.9.9/0000755000000000000000000000000011244274432011664 5ustar rootrootksplice-0.9.9/ChangeLog0000644000000000000000000000765611244274432013454 0ustar rootroot2009-08-23 : 0.9.9 - Added support for applying an already unpacked update tree - Fixed ksplice-create when installed to a prefix other than /usr/local - Improved stack check completeness for self-restarting syscalls 2009-07-12 : 0.9.8 - Improved error handling in the Ksplice perl utilities - Updated Ksplice for kernel 2.6.30 - Fixed several bugs in the handling of bugline patches 2009-03-10 : 0.9.7 - Fixed a bug where Ksplice relocations were sometimes written pointing to the middle of patched sections - Fixed a Makefile bug where the Ksplice core module was compiled twice - Renamed or reorganized several data structures in the Ksplice kernel code - Changed the Ksplice module names from primary/helper to old_code/new_code 2009-01-21 : 0.9.6 - Fixed a Makefile bug that prevented the initial prebuild from succeeding - Documented the ksplice-create --series, --git, and --build-modules options - Added support for changing CRCs of exported symbols - Added pre-post matching of altinstructions and other table sections - Fixed a build failure due to depmod when using a kbuild output directory 2008-12-19 : 0.9.5 - Added support for building updates from Git commits in ksplice-create - Prevent reversing Ksplice updates that have been partially cold applied 2008-11-21 : 0.9.4 - Added support for patching kernels built in a separate Kbuild output directory (O=dir) - Added additional metadata to the Ksplice update tarballs - Updated Ksplice for kernel 2.6.28 2008-11-07 : 0.9.3 - Added hooks for calling functions at various points during the update process - Added support for applying an update only to loaded target modules - Added support for building updated target modules along with a Ksplice update - Added run-pre matching of the bug table, exception table, and exported symbol table - Improved robustness of the stack check with respect to optimized tail calls - Fixed several bugs in the run-pre matching disassembly code - Added patching of rodata sections that did not change in size - Added patching of bug table entries whose line numbers changed - Added an experimental API for shadow data structures 2008-10-17 : 0.9.2 - Added run-pre matching of string sections - Fixed safety_record handling for patch reversals - Improved performance substantially in both userspace and kernelspace - Added support for patching kernels whose text is mapped read-only - Added support for patching compilation units involving markers - Improved the udis86 disassembler's support for disassembling the kernel 2008-09-26 : 0.9.1 - Replaced objdiff with an improved matching algorithm in objmanip keep-primary - Added support for moving functions between compilation units - Various safety improvements 2008-09-12 : 0.9.0 - Added support for ARM architecture (requires an -ffunction-sections kernel) - Rewrote the relocation handling code to ease porting to other architectures - Modified the update build system so that it uses the kernel build system - Switched the module control interface from /proc to /sys - Switched the preferred debugging interface from printk to debugfs - Restructured the kernel code to make it easier to merge Ksplice into Linux - Simplified ksplice-create by moving all ELF manipulation to objmanip - Added libudis86 for enhanced run-pre matching - Added support for automatically modifying the exported symbol table - Various safety improvements 2008-06-22 : 0.8.7 - Updated the nop table for binutils 2.18 - Improved relocation handling on x86-64 2008-05-25 : 0.8.6 - Removed some compiler warnings 2008-05-24 : 0.8.5 - Added a workaround for Fedora System.map problem - Improved the page table code - Improved kernel stack check debugging 2008-04-29 : 0.8.4 - Fixed architecture detection on ASP Linux 2008-04-28 : 0.8.3 - Improved kernel stack check 2008-04-27 : 0.8.2 - Improved kernel stack check 2008-04-24 : 0.8.1 - Fixed 2.6.25 init_mm problem 2008-04-22 : 0.8.0 - Initial release ksplice-0.9.9/inspect.c0000644000000000000000000002563511244274432013510 0ustar rootroot/* Copyright (C) 2008-2009 Ksplice, Inc. * Authors: Anders Kaseorg, Tim Abbott, Jeff Arnold * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA * 02110-1301, USA. */ /* Always define KSPLICE_STANDALONE, even if you're using integrated Ksplice. inspect won't compile without it. */ #define KSPLICE_STANDALONE #define _GNU_SOURCE #include "objcommon.h" #include "kmodsrc/ksplice.h" #include char *str_pointer(struct supersect *ss, void *const *addr); struct kreloc_section { struct supersect *ss; const struct ksplice_reloc *reloc; }; #define kreloc_section_init(ks) *(ks) = NULL DEFINE_HASH_TYPE(struct kreloc_section *, kreloc_section_hash, kreloc_section_hash_init, kreloc_section_hash_free, kreloc_section_hash_lookup, kreloc_section_init); struct kreloc_section_hash ksplice_relocs; char *str_ulong_vec(struct supersect *ss, const unsigned long *const *datap, const unsigned long *sizep) { struct supersect *data_ss; const unsigned long *data = read_pointer(ss, (void *const *)datap, &data_ss); unsigned long size = read_num(ss, sizep); char *buf = NULL; size_t bufsize = 0; FILE *fp = open_memstream(&buf, &bufsize); fprintf(fp, "[ "); size_t i; for (i = 0; i < size; ++i) fprintf(fp, "%lx ", read_num(data_ss, &data[i])); fprintf(fp, "]"); fclose(fp); return buf; } static const struct ksplice_reloc * find_ksplice_reloc(struct supersect *ss, void *const *addr, struct supersect **reloc_ss) { char *key = strprintf("%p", addr); struct kreloc_section **ksp = kreloc_section_hash_lookup(&ksplice_relocs, key, FALSE); free(key); if (ksp == NULL) return NULL; *reloc_ss = (*ksp)->ss; return (*ksp)->reloc; } char *str_ksplice_symbol(struct supersect *ss, const struct ksplice_symbol *ksymbol) { return strprintf("%s (%s)", read_string(ss, &ksymbol->label), read_string(ss, &ksymbol->name)); } char *str_ksplice_symbolp(struct supersect *ptr_ss, struct ksplice_symbol *const *ksymbolp) { asymbol *sym; bfd_vma offset = read_reloc(ptr_ss, ksymbolp, sizeof(*ksymbolp), &sym); if (bfd_is_const_section(sym->section)) return strprintf("*(%s)", str_pointer(ptr_ss, (void *const *)ksymbolp)); struct supersect *ksymbol_ss = fetch_supersect(ptr_ss->parent, sym->section); return str_ksplice_symbol(ksymbol_ss, ksymbol_ss->contents.data + sym->value + offset); } char *str_pointer(struct supersect *ss, void *const *addr) { asymbol *sym; struct supersect *kreloc_ss; const struct ksplice_reloc *kreloc = find_ksplice_reloc(ss, addr, &kreloc_ss); if (kreloc == NULL) { bfd_vma offset = read_reloc(ss, addr, sizeof(*addr), &sym); return strprintf("%s+%lx", sym->name, (unsigned long)offset); } else { return strprintf("[%s]+%lx", str_ksplice_symbolp(kreloc_ss, &kreloc->symbol), kreloc->target_addend); } } static const char *str_howto_type(const struct ksplice_reloc_howto *howto) { switch (howto->type) { case KSPLICE_HOWTO_RELOC: return "reloc"; case KSPLICE_HOWTO_RELOC_PATCH: return "reloc(patch)"; case KSPLICE_HOWTO_TIME: return "time"; case KSPLICE_HOWTO_DATE: return "date"; case KSPLICE_HOWTO_BUG: return "bug"; case KSPLICE_HOWTO_EXTABLE: return "extable"; case KSPLICE_HOWTO_SYMBOL: return "symbol"; default: return "unknown"; } } void show_ksplice_reloc(struct supersect *ss, const struct ksplice_reloc *kreloc) { struct supersect *khowto_ss; const struct ksplice_reloc_howto *khowto = read_pointer(ss, (void *const *)&kreloc->howto, &khowto_ss); printf(" blank_addr: %s size: %x\n" " type: %s\n" " symbol: %s\n" " insn_addend: %lx\n" " target_addend: %lx\n" " pcrel: %x dst_mask: %lx rightshift: %x signed_addend: %x\n" "\n", str_pointer(ss, (void *const *)&kreloc->blank_addr), read_num(khowto_ss, &khowto->size), str_howto_type(khowto), str_ksplice_symbolp(ss, &kreloc->symbol), read_num(ss, &kreloc->insn_addend), read_num(ss, &kreloc->target_addend), read_num(khowto_ss, &khowto->pcrel), read_num(khowto_ss, &khowto->dst_mask), read_num(khowto_ss, &khowto->rightshift), read_num(khowto_ss, &khowto->signed_addend)); } void show_ksplice_relocs(struct supersect *kreloc_ss) { const struct ksplice_reloc *kreloc; for (kreloc = kreloc_ss->contents.data; (void *)kreloc < kreloc_ss->contents.data + kreloc_ss->contents.size; kreloc++) show_ksplice_reloc(kreloc_ss, kreloc); } void show_ksplice_section_flags(const struct ksplice_section *ksect) { printf(" flags:"); if (ksect->flags & KSPLICE_SECTION_RODATA) printf(" rodata"); if (ksect->flags & KSPLICE_SECTION_TEXT) printf(" text"); if (ksect->flags & KSPLICE_SECTION_DATA) printf(" data"); if (ksect->flags & KSPLICE_SECTION_MATCH_DATA_EARLY) printf(" match_early"); printf("\n"); } void show_ksplice_section(struct supersect *ss, const struct ksplice_section *ksect) { printf(" symbol: %s\n" " address: %s size: %lx\n", str_ksplice_symbolp(ss, &ksect->symbol), str_pointer(ss, (void *const *)&ksect->address), read_num(ss, &ksect->size)); show_ksplice_section_flags(ksect); printf("\n"); } void show_ksplice_sections(struct supersect *ksect_ss) { struct ksplice_section *ksect; for (ksect = ksect_ss->contents.data; (void *)ksect < ksect_ss->contents.data + ksect_ss->contents.size; ksect++) show_ksplice_section(ksect_ss, ksect); } const char *str_ksplice_patch_type(struct supersect *ss, const struct ksplice_patch *kpatch) { const char *const *strp; struct supersect *data_ss; switch(kpatch->type) { case KSPLICE_PATCH_TEXT: return strprintf("text\n repladdr: %s", str_pointer (ss, (void *const *)&kpatch->repladdr)); case KSPLICE_PATCH_DATA: return strprintf("data\n size: %x", kpatch->size); case KSPLICE_PATCH_EXPORT: strp = read_pointer(ss, &kpatch->contents, &data_ss); return strprintf("export\n newname: %s", read_string(data_ss, strp)); default: return "unknown"; } } void show_ksplice_patch(struct supersect *ss, const struct ksplice_patch *kpatch) { printf(" type: %s\n" " oldaddr: %s\n\n", str_ksplice_patch_type(ss, kpatch), str_pointer(ss, (void *const *)&kpatch->oldaddr)); } void show_ksplice_patches(struct supersect *kpatch_ss) { const struct ksplice_patch *kpatch; for (kpatch = kpatch_ss->contents.data; (void *)kpatch < kpatch_ss->contents.data + kpatch_ss->contents.size; kpatch++) show_ksplice_patch(kpatch_ss, kpatch); } void show_ksplice_call(struct supersect *ss, void *const *kcall) { printf("%s\n", str_pointer(ss, kcall)); } void show_ksplice_calls(struct supersect *kcall_ss) { void *const *kcall; for (kcall = kcall_ss->contents.data; (void *)kcall < kcall_ss->contents.data + kcall_ss->contents.size; kcall++) show_ksplice_call(kcall_ss, kcall); } void show_ksplice_system_map(struct supersect *ss, const struct ksplice_system_map *smap) { printf("%s %s\n", read_string(ss, &smap->label), str_ulong_vec(ss, &smap->candidates, &smap->nr_candidates)); } void show_ksplice_system_maps(struct supersect *smap_ss) { const struct ksplice_system_map *smap; for (smap = smap_ss->contents.data; (void *)smap < smap_ss->contents.data + smap_ss->contents.size; smap++) show_ksplice_system_map(smap_ss, smap); } struct inspect_section { const char *prefix; const char *header; const char *notfound; void (*show)(struct supersect *ss); }; const struct inspect_section inspect_sections[] = { { .prefix = ".ksplice_init_relocs", .header = "KSPLICE INIT RELOCATIONS", .notfound = "No ksplice init relocations.\n", .show = show_ksplice_relocs, }, { .prefix = ".ksplice_relocs", .header = "KSPLICE RELOCATIONS", .notfound = "No ksplice relocations.\n", .show = show_ksplice_relocs, }, { .prefix = ".ksplice_sections", .header = "KSPLICE SECTIONS", .notfound = "No ksplice sections.\n", .show = show_ksplice_sections, }, { .prefix = ".ksplice_patches", .header = "KSPLICE PATCHES", .notfound = "No ksplice patches.\n", .show = show_ksplice_patches, }, { .prefix = ".ksplice_call", .header = "KSPLICE CALLS", .notfound = "No ksplice calls.\n", .show = show_ksplice_calls, }, { .prefix = ".ksplice_system_map", .header = "KSPLICE SYSTEM.MAP", .notfound = "No ksplice System.map.\n", .show = show_ksplice_system_maps, }, }, *const inspect_sections_end = *(&inspect_sections + 1); static void load_ksplice_reloc_offsets(struct superbfd *sbfd) { kreloc_section_hash_init(&ksplice_relocs); asection *sect; for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(sbfd, sect); if (!strstarts(ss->name, ".ksplice_relocs") && !strstarts(ss->name, ".ksplice_init_relocs")) continue; struct ksplice_reloc *kreloc; for (kreloc = ss->contents.data; (void *)kreloc < ss->contents.data + ss->contents.size; kreloc++) { const struct ksplice_reloc_howto *khowto = read_pointer(ss, (void *const *)&kreloc->howto, NULL); if (khowto->size == 0) continue; struct supersect *sym_ss; const void *ptr = read_pointer(ss, (void *const *)&kreloc->blank_addr, &sym_ss); char *key = strprintf("%p", ptr); struct kreloc_section *ks, **ksp = kreloc_section_hash_lookup(&ksplice_relocs, key, TRUE); free(key); assert(*ksp == NULL); ks = malloc(sizeof(*ks)); *ksp = ks; ks->reloc = kreloc; ks->ss = ss; } } } static void show_inspect_section(struct superbfd *sbfd, const struct inspect_section *isect) { bool found = false; asection *sect; for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(sbfd, sect); if (strstarts(ss->name, isect->prefix) && ss->contents.size != 0) { printf("%s IN [%s]:\n", isect->header, sect->name); found = true; isect->show(ss); } } if (!found) printf("%s", isect->notfound); printf("\n"); } int main(int argc, char *argv[]) { bfd *ibfd; assert(argc >= 1); bfd_init(); ibfd = bfd_openr(argv[1], NULL); assert(ibfd); char **matching; assert(bfd_check_format_matches(ibfd, bfd_object, &matching)); struct superbfd *sbfd = fetch_superbfd(ibfd); load_ksplice_reloc_offsets(sbfd); const struct inspect_section *isect; for (isect = inspect_sections; isect < inspect_sections_end; isect++) show_inspect_section(sbfd, isect); return 0; } ksplice-0.9.9/kmodsrc/0000755000000000000000000000000011244274432013326 5ustar rootrootksplice-0.9.9/kmodsrc/offsets.c0000644000000000000000000001647611244274432015161 0ustar rootroot/* Copyright (C) 2008-2009 Ksplice, Inc. * Authors: Anders Kaseorg, Tim Abbott, Jeff Arnold * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA * 02110-1301, USA. */ #include #include #include #include #include #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) /* 63104eec234bdecb55fd9c15467ae00d0a3f42ac was after 2.6.17 */ #include #endif /* LINUX_VERSION_CODE */ #ifdef CONFIG_PARAVIRT #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) /* 98de032b681d8a7532d44dfc66aa5c0c1c755a9d was after 2.6.21 */ #define paravirt_patch_site paravirt_patch #endif /* LINUX_VERSION_CODE */ #endif /* CONFIG_PARAVIRT */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) /* 8256e47cdc8923e9959eb1d7f95d80da538add80 was after 2.6.23 */ #include #endif /* LINUX_VERSION_CODE */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) /* 97e1c18e8d17bd87e1e383b2e9d9fc740332c8e2 was after 2.6.27 */ #include #endif /* LINUX_VERSION_CODE */ #include #include "offsets.h" const struct ksplice_config config __attribute__((section(".ksplice_config"))) = { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) /* eb8f689046b857874e964463619f09df06d59fad was after 2.6.24 */ /* Introduction of .cpuinit, .devinit, .meminit sections */ #ifndef CONFIG_HOTPLUG .ignore_devinit = 1, #endif /* !CONFIG_HOTPLUG */ #ifndef CONFIG_HOTPLUG_CPU .ignore_cpuinit = 1, #endif /* !CONFIG_HOTPLUG_CPU */ #ifndef CONFIG_MEMORY_HOTPLUG .ignore_meminit = 1, #endif /* !CONFIG_MEMORY_HOTPLUG */ #endif /* LINUX_VERSION_CODE */ }; #define FIELD_ENDOF(t, f) (offsetof(t, f) + FIELD_SIZEOF(t, f)) const struct table_section table_sections[] __attribute__((section(".ksplice_table_sections"))) = { #ifdef CONFIG_X86 { .sect = ".altinstructions", .entry_size = sizeof(struct alt_instr), #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) .entry_contents_size = offsetof(struct alt_instr, pad1), #else /* 1d8a1f6b51f6b195dfdcf05821be97edede5664a was after 2.6.24 */ .entry_contents_size = offsetof(struct alt_instr, pad), #endif .entry_align = __alignof__(struct alt_instr), .has_addr = 1, .addr_offset = offsetof(struct alt_instr, instr), .other_sect = ".altinstr_replacement", .other_offset = offsetof(struct alt_instr, replacement), }, #endif /* CONFIG_X86 */ #if defined CONFIG_GENERIC_BUG && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) { .sect = "__bug_table", .entry_size = sizeof(struct bug_entry), .entry_contents_size = FIELD_ENDOF(struct bug_entry, flags), .entry_align = __alignof__(struct bug_entry), .has_addr = 1, #ifdef CONFIG_GENERIC_BUG_RELATIVE_POINTERS .relative_addr = 1, .addr_offset = offsetof(struct bug_entry, bug_addr_disp), .relative_other = 1, .other_offset = offsetof(struct bug_entry, file_disp), #else .addr_offset = offsetof(struct bug_entry, bug_addr), #endif }, #else /* !CONFIG_GENERIC_BUG || LINUX_VERSION_CODE < */ /* 91768d6c2bad0d2766a166f13f2f57e197de3458 was after 2.6.19 */ #endif /* CONFIG_GENERIC_BUG && LINUX_VERSION_CODE */ { .sect = "__ex_table", .entry_size = sizeof(struct exception_table_entry), .entry_align = __alignof__(struct exception_table_entry), .has_addr = 1, .addr_offset = offsetof(struct exception_table_entry, insn), .other_sect = ".fixup", .other_offset = offsetof(struct exception_table_entry, fixup), }, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) /* 8256e47cdc8923e9959eb1d7f95d80da538add80 was after 2.6.23 */ { .sect = "__markers", .entry_size = sizeof(struct marker), .entry_align = __alignof__(struct marker), .other_sect = "__markers_strings", .other_offset = offsetof(struct marker, name), }, #endif /* LINUX_VERSION_CODE */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) /* 97e1c18e8d17bd87e1e383b2e9d9fc740332c8e2 was after 2.6.27 */ { .sect = "__tracepoints", .entry_size = sizeof(struct tracepoint), .entry_align = __alignof__(struct tracepoint), .other_sect = "__tracepoints_strings", .other_offset = offsetof(struct tracepoint, name), }, #endif /* LINUX_VERSION_CODE */ #ifdef CONFIG_PARAVIRT { .sect = ".parainstructions", .entry_size = sizeof(struct paravirt_patch_site), .entry_contents_size = FIELD_ENDOF(struct paravirt_patch_site, clobbers), .entry_align = __alignof__(struct paravirt_patch_site), .has_addr = 1, .addr_offset = offsetof(struct paravirt_patch_site, instr), }, #endif /* CONFIG_PARAVIRT */ { .sect = ".smp_locks", .entry_size = sizeof(u8 *), .entry_align = __alignof__(u8 *), .has_addr = 1, .addr_offset = 0, }, { .sect = "__ksymtab", .entry_size = sizeof(struct kernel_symbol), .entry_align = __alignof__(struct kernel_symbol), .other_offset = offsetof(struct kernel_symbol, name), #ifdef CONFIG_MODVERSIONS .crc_size = sizeof(unsigned long), .crc_sect = "__kcrctab", #endif /* CONFIG_MODVERSIONS */ }, { .sect = "__ksymtab_gpl", .entry_size = sizeof(struct kernel_symbol), .entry_align = __alignof__(struct kernel_symbol), .other_offset = offsetof(struct kernel_symbol, name), #ifdef CONFIG_MODVERSIONS .crc_size = sizeof(unsigned long), .crc_sect = "__kcrctab_gpl", #endif /* CONFIG_MODVERSIONS */ }, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) && defined(CONFIG_UNUSED_SYMBOLS) /* f71d20e961474dde77e6558396efb93d6ac80a4b was after 2.6.17 */ { .sect = "__ksymtab_unused_gpl", .entry_size = sizeof(struct kernel_symbol), .entry_align = __alignof__(struct kernel_symbol), .other_offset = offsetof(struct kernel_symbol, name), #ifdef CONFIG_MODVERSIONS .crc_size = sizeof(unsigned long), .crc_sect = "__kcrctab_unused_gpl", #endif /* CONFIG_MODVERSIONS */ }, { .sect = "__ksymtab_unused", .entry_size = sizeof(struct kernel_symbol), .entry_align = __alignof__(struct kernel_symbol), .other_offset = offsetof(struct kernel_symbol, name), #ifdef CONFIG_MODVERSIONS .crc_size = sizeof(unsigned long), .crc_sect = "__kcrctab_unused", #endif /* CONFIG_MODVERSIONS */ }, #endif /* LINUX_VERSION_CODE */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) /* 9f28bb7e1d0188a993403ab39b774785892805e1 was after 2.6.16 */ { .sect = "__ksymtab_gpl_future", .entry_size = sizeof(struct kernel_symbol), .entry_align = __alignof__(struct kernel_symbol), .other_offset = offsetof(struct kernel_symbol, name), #ifdef CONFIG_MODVERSIONS .crc_size = sizeof(unsigned long), .crc_sect = "__kcrctab_gpl_future", #endif /* CONFIG_MODVERSIONS */ }, #endif /* LINUX_VERSION_CODE */ }; const char *__attribute__((section(".uts_sysname"))) sysname = UTS_SYSNAME; const char *__attribute__((section(".uts_release"))) release = UTS_RELEASE; const char *__attribute__((section(".uts_version"))) version = UTS_VERSION; const char *__attribute__((section(".uts_machine"))) machine = UTS_MACHINE; ksplice-0.9.9/kmodsrc/offsets.h0000644000000000000000000000054111244274432015150 0ustar rootrootstruct table_section { const char *sect; int entry_size; int entry_contents_size; int entry_align; int has_addr; int relative_addr; int addr_offset; const char *other_sect; int relative_other; int other_offset; const char *crc_sect; int crc_size; }; struct ksplice_config { int ignore_devinit; int ignore_cpuinit; int ignore_meminit; }; ksplice-0.9.9/kmodsrc/ksplice-rmsyms.lds0000644000000000000000000000051711244274432017017 0ustar rootrootSECTIONS { /DISCARD/ : { *(.ksplice_extract .ksplice_relocs.ksplice_extract) } .ksplice_init_relocs : { ksplice_init_relocs = .; KEEP(*(.ksplice_relocs*)) ksplice_init_relocs_end = .; } .ksplice_system_map : { ksplice_system_map = .; KEEP(*(.ksplice_system_map)) ksplice_system_map_end = .; } } ksplice-0.9.9/kmodsrc/new_code_loader.c0000644000000000000000000001024411244274432016604 0ustar rootroot/* Copyright (C) 2007-2009 Ksplice, Inc. * Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA * 02110-1301, USA. */ #ifdef KSPLICE_STANDALONE #include "ksplice.h" #else #include #endif extern struct ksplice_reloc ksplice_relocs[], ksplice_relocs_end[]; extern struct ksplice_section ksplice_sections[], ksplice_sections_end[]; extern struct ksplice_symbol ksplice_symbols[], ksplice_symbols_end[]; extern struct ksplice_patch ksplice_patches[], ksplice_patches_end[]; extern const typeof(int (*)(void)) ksplice_call_pre_apply[], ksplice_call_pre_apply_end[], ksplice_call_check_apply[], ksplice_call_check_apply_end[]; extern const typeof(void (*)(void)) ksplice_call_apply[], ksplice_call_apply_end[], ksplice_call_post_apply[], ksplice_call_post_apply_end[], ksplice_call_fail_apply[], ksplice_call_fail_apply_end[]; extern const typeof(int (*)(void)) ksplice_call_pre_reverse[], ksplice_call_pre_reverse_end[], ksplice_call_check_reverse[], ksplice_call_check_reverse_end[]; extern const typeof(void (*)(void)) ksplice_call_reverse[], ksplice_call_reverse_end[], ksplice_call_post_reverse[], ksplice_call_post_reverse_end[], ksplice_call_fail_reverse[], ksplice_call_fail_reverse_end[]; #ifdef KSPLICE_NEED_PARAINSTRUCTIONS extern struct paravirt_patch_site parainstructions[], parainstructions_end[]; #endif #ifdef KSPLICE_STANDALONE extern struct ksplice_system_map ksplice_system_map[], ksplice_system_map_end[]; #endif /* KSPLICE_STANDALONE */ #define change KSPLICE_UNIQ(change) struct ksplice_mod_change change = { .name = "ksplice_" __stringify(KSPLICE_MID), .kid = __stringify(KSPLICE_KID), .target_name = __stringify(KSPLICE_TARGET), #ifdef KSPLICE_STANDALONE .map_printk = MAP_PRINTK, #endif /* KSPLICE_STANDALONE */ .new_code_mod = THIS_MODULE, .new_code = { .relocs = ksplice_relocs, .relocs_end = ksplice_relocs_end, .sections = ksplice_sections, .sections_end = ksplice_sections_end, .symbols = ksplice_symbols, .symbols_end = ksplice_symbols_end, #ifdef KSPLICE_NEED_PARAINSTRUCTIONS .parainstructions = parainstructions, .parainstructions_end = parainstructions_end, #endif #ifdef KSPLICE_STANDALONE .system_map = ksplice_system_map, .system_map_end = ksplice_system_map_end, #endif /* KSPLICE_STANDALONE */ }, .patches = ksplice_patches, .patches_end = ksplice_patches_end, .hooks = { [KS_APPLY] = { .pre = ksplice_call_pre_apply, .pre_end = ksplice_call_pre_apply_end, .check = ksplice_call_check_apply, .check_end = ksplice_call_check_apply_end, .intra = ksplice_call_apply, .intra_end = ksplice_call_apply_end, .post = ksplice_call_post_apply, .post_end = ksplice_call_post_apply_end, .fail = ksplice_call_fail_apply, .fail_end = ksplice_call_fail_apply_end, }, [KS_REVERSE] = { .pre = ksplice_call_pre_reverse, .pre_end = ksplice_call_pre_reverse_end, .check = ksplice_call_check_reverse, .check_end = ksplice_call_check_reverse_end, .intra = ksplice_call_reverse, .intra_end = ksplice_call_reverse_end, .post = ksplice_call_post_reverse, .post_end = ksplice_call_post_reverse_end, .fail = ksplice_call_fail_reverse, .fail_end = ksplice_call_fail_reverse_end, }, }, }; EXPORT_SYMBOL_GPL(change); static int init_new_code(void) { return 0; } static void cleanup_new_code(void) { cleanup_ksplice_mod_change(&change); } module_init(init_new_code); module_exit(cleanup_new_code); MODULE_AUTHOR("Ksplice, Inc."); MODULE_DESCRIPTION("Ksplice rebootless update new code module"); #ifdef KSPLICE_VERSION MODULE_VERSION(KSPLICE_VERSION); #endif MODULE_LICENSE("GPL v2"); ksplice-0.9.9/kmodsrc/Makefile.in0000644000000000000000000000663511244274432015405 0ustar rootrootprefix = @prefix@ datarootdir = @datarootdir@ datadir = @datadir@ ksplice-script = $(datadir)/ksplice/ksplice-obj.pl KSPLICE_KID ?= $(error "You must set KSPLICE_KID.") KSPLICE_VERSION ?= $(error "You must set KSPLICE_VERSION.") map_printk ?= $(error "You must set map_printk.") ifneq ($(KSPLICE_STANDALONE),) KSPLICE_CFLAGS += -DKSPLICE_STANDALONE endif KSPLICE_CFLAGS += -DKSPLICE_KID=$(KSPLICE_KID) KSPLICE_CFLAGS += -DMAP_PRINTK=0x$(map_printk)L comma ?= , name-fix ?= $(subst $(comma),_,$(subst -,_,$(1))) target = $(call name-fix,$(mod)) KSPLICE_MID = $(KSPLICE_KID)_$(target) KSPLICE = ksplice-$(KSPLICE_MID) KSPLICE_CORE = ksplice-$(KSPLICE_KID) quiet_cmd_ksplice-collect = COLLECT $@ cmd_ksplice-collect = \ $(ksplice-script) finalize $< $<.final $* && \ $(LD) --script=$(obj)/ksplice.lds -r -o $@ $<.final ksplice-mod-cflags = $(KSPLICE_CFLAGS) \ "-DKSPLICE_MID=$(KSPLICE_MID)" \ $(addprefix -DKSPLICE_TARGET=,$(target)) \ "-DKSPLICE_VERSION=\"$(KSPLICE_VERSION)\"" ksplice-new-code-objs = new-code-$(target).o collect-new-code-$(mod).o ksplice-old-code-objs = old-code-$(target).o collect-old-code-$(mod).o ifneq ($(KSPLICE_STANDALONE),) ifeq ($(KSPLICE_SKIP_CORE),) obj-m += $(KSPLICE_CORE).o endif UDIS86 = x86/libudis86 kudis86 += \ $(UDIS86)/itab.o \ $(UDIS86)/input.o \ $(UDIS86)/decode.o \ $(UDIS86)/syn.o \ $(UDIS86)/syn-intel.o \ $(UDIS86)/syn-att.o \ $(UDIS86)/udis86.o $(KSPLICE_CORE)-objs = $(fake-ksplice.o) ksplice-rmsyms.o $(kudis86) fake-ksplice.o = ksplice.o $(obj)/$(KSPLICE_CORE).o: fake-ksplice.o = endif define ksplice-mod-vars ifneq ($(KSPLICE_SHORT_NAME_HACK),) obj-m += $(KSPLICE)-n.o $(KSPLICE)-o.o $(KSPLICE)-n-objs = $(ksplice-new-code-objs) $(KSPLICE)-o-objs = $(ksplice-old-code-objs) else obj-m += $(KSPLICE)-new.o $(KSPLICE)-old.o $(KSPLICE)-new-objs = $(ksplice-new-code-objs) $(KSPLICE)-old-objs = $(ksplice-old-code-objs) endif CFLAGS_new-code-$(target).o = $(ksplice-mod-cflags) CFLAGS_old-code-$(target).o = $(ksplice-mod-cflags) CPPFLAGS_ksplice.lds = $(ksplice-mod-cflags) -P endef $(foreach mod,$(KSPLICE_MODULES),$(eval $(ksplice-mod-vars))) ifneq ($(KSPLICE_MODULES),) $(foreach mod,$(KSPLICE_MODULES),$(obj)/new-code-$(target).o): $(obj)/%.o: $(src)/new_code_loader.c FORCE $(call if_changed_rule,cc_o_c) $(foreach mod,$(KSPLICE_MODULES),$(obj)/old-code-$(target).o): $(obj)/%.o: $(src)/old_code_loader.c FORCE $(call if_changed_rule,cc_o_c) endif $(obj)/collect-new-code-%.o: $(obj)/%.o.KSPLICE_new_code $(obj)/ksplice.lds FORCE $(call if_changed,ksplice-collect) $(obj)/collect-old-code-%.o: $(obj)/%.o.KSPLICE_old_code $(obj)/ksplice.lds FORCE $(call if_changed,ksplice-collect) ifeq ($(quiet_cmd_cpp_lds_S),) quiet_cmd_cpp_lds_S = LDS $@ cmd_cpp_lds_S = $(CPP) -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) $(EXTRA_CPPFLAGS) $(CPPFLAGS_$(@F)) $(cpp_flags) -D__ASSEMBLY__ -o $@ $< %.lds: %.lds.S FORCE $(call if_changed_dep,cpp_lds_S) endif $(obj)/ksplice.lds: $(src)/ksplice.lds.S FORCE $(call if_changed_dep,cpp_lds_S) CFLAGS_offsets.o += $(KSPLICE_CFLAGS) ifeq ($(KSPLICE_SKIP_CORE),) extra-y += offsets.o endif ifneq ($(KSPLICE_STANDALONE),) CFLAGS_ksplice.o += $(KSPLICE_CFLAGS) quiet_cmd_ksplice-rmsyms = RMSYMS $@ cmd_ksplice-rmsyms = \ $(ksplice-script) rmsyms $< $<.rmsyms && \ $(LD) --script=$(src)/ksplice-rmsyms.lds -r -o $@ $<.rmsyms $(obj)/ksplice-rmsyms.o: $(obj)/ksplice.o $(obj)/offsets.o FORCE $(call if_changed,ksplice-rmsyms) endif # KSPLICE_STANDALONE ksplice-0.9.9/kmodsrc/ksplice.c0000644000000000000000000037445411244274432015145 0ustar rootroot/* Copyright (C) 2007-2009 Ksplice, Inc. * Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA * 02110-1301, USA. */ #include #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) #include #else /* LINUX_VERSION_CODE */ /* 7664c5a1da4711bb6383117f51b94c8dc8f3f1cd was after 2.6.19 */ #endif /* LINUX_VERSION_CODE */ #include #if defined CONFIG_DEBUG_FS || LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) #include #else /* CONFIG_DEBUG_FS */ /* a7a76cefc4b12bb6508afa4c77f11c2752cc365d was after 2.6.11 */ #endif /* CONFIG_DEBUG_FS */ #include #include #include #include #include #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) #include #else /* LINUX_VERSION_CODE < */ /* 8c63b6d337534a6b5fb111dc27d0850f535118c0 was after 2.6.11 */ #endif /* LINUX_VERSION_CODE */ #include #include #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) #include #else /* LINUX_VERSION_CODE < */ /* linux/uaccess.h doesn't exist in kernels before 2.6.18 */ #include #endif /* LINUX_VERSION_CODE */ #include #ifdef KSPLICE_STANDALONE #include "ksplice.h" #else /* !KSPLICE_STANDALONE */ #include #endif /* KSPLICE_STANDALONE */ #ifdef KSPLICE_NEED_PARAINSTRUCTIONS #include #endif /* KSPLICE_NEED_PARAINSTRUCTIONS */ #ifdef KSPLICE_STANDALONE #if !defined(CONFIG_KSPLICE) && !defined(CONFIG_KSPLICE_MODULE) #define KSPLICE_NO_KERNEL_SUPPORT 1 #endif /* !CONFIG_KSPLICE && !CONFIG_KSPLICE_MODULE */ #ifndef __used #define __used __attribute_used__ #endif #define EXTRACT_SYMBOL(sym) \ static const typeof(&sym) PASTE(__ksplice_extract_, __LINE__) \ __used __attribute__((section(".ksplice_extract"))) = &sym #endif /* KSPLICE_STANDALONE */ enum stage { STAGE_PREPARING, /* the update is not yet applied */ STAGE_APPLIED, /* the update is applied */ STAGE_REVERSED, /* the update has been applied and reversed */ }; /* parameter to modify run-pre matching */ enum run_pre_mode { RUN_PRE_INITIAL, /* dry run (only change temp_labelvals) */ RUN_PRE_DEBUG, /* dry run with byte-by-byte debugging */ RUN_PRE_FINAL, /* finalizes the matching */ #ifndef CONFIG_FUNCTION_DATA_SECTIONS RUN_PRE_SILENT, #endif /* !CONFIG_FUNCTION_DATA_SECTIONS */ }; enum { NOVAL, TEMP, VAL }; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) /* 5d7b32de9935c65ca8285ac6ec2382afdbb5d479 was after 2.6.8 */ #define __bitwise__ #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) /* af4ca457eaf2d6682059c18463eb106e2ce58198 was after 2.6.14 */ #define __bitwise__ __bitwise #endif typedef int __bitwise__ abort_t; #define OK ((__force abort_t) 0) #define NO_MATCH ((__force abort_t) 1) #define CODE_BUSY ((__force abort_t) 2) #define MODULE_BUSY ((__force abort_t) 3) #define OUT_OF_MEMORY ((__force abort_t) 4) #define FAILED_TO_FIND ((__force abort_t) 5) #define ALREADY_REVERSED ((__force abort_t) 6) #define MISSING_EXPORT ((__force abort_t) 7) #define UNEXPECTED_RUNNING_TASK ((__force abort_t) 8) #define UNEXPECTED ((__force abort_t) 9) #define TARGET_NOT_LOADED ((__force abort_t) 10) #define CALL_FAILED ((__force abort_t) 11) #define COLD_UPDATE_LOADED ((__force abort_t) 12) #ifdef KSPLICE_STANDALONE #define BAD_SYSTEM_MAP ((__force abort_t) 13) #endif /* KSPLICE_STANDALONE */ struct update { const char *kid; const char *name; struct kobject kobj; enum stage stage; abort_t abort_cause; int debug; #ifdef CONFIG_DEBUG_FS struct debugfs_blob_wrapper debug_blob; struct dentry *debugfs_dentry; #else /* !CONFIG_DEBUG_FS */ bool debug_continue_line; #endif /* CONFIG_DEBUG_FS */ bool partial; /* is it OK if some target mods aren't loaded */ struct list_head changes, /* changes for loaded target mods */ unused_changes; /* changes for non-loaded target mods */ struct list_head conflicts; struct list_head list; struct list_head ksplice_module_list; }; /* a process conflicting with an update */ struct conflict { const char *process_name; pid_t pid; struct list_head stack; struct list_head list; }; /* an address on the stack of a conflict */ struct conflict_addr { unsigned long addr; /* the address on the stack */ bool has_conflict; /* does this address in particular conflict? */ const char *label; /* the label of the conflicting safety_record */ struct list_head list; }; #if defined(CONFIG_DEBUG_FS) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) /* Old kernels don't have debugfs_create_blob */ struct debugfs_blob_wrapper { void *data; unsigned long size; }; #endif /* CONFIG_DEBUG_FS && LINUX_VERSION_CODE */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) /* 930631edd4b1fe2781d9fe90edbe35d89dfc94cc was after 2.6.18 */ #define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) #endif struct labelval { struct list_head list; struct ksplice_symbol *symbol; struct list_head *saved_vals; }; /* region to be checked for conflicts in the stack check */ struct safety_record { struct list_head list; const char *label; unsigned long addr; /* the address to be checked for conflicts * (e.g. an obsolete function's starting addr) */ unsigned long size; /* the size of the region to be checked */ }; /* possible value for a symbol */ struct candidate_val { struct list_head list; unsigned long val; }; /* private struct used by init_symbol_array */ struct ksplice_lookup { /* input */ struct ksplice_mod_change *change; struct ksplice_symbol **arr; size_t size; /* output */ abort_t ret; }; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) /* c6b37801911d7f4663c99cad8aa230bc934cea82 was after 2.6.29 */ struct symsearch { const struct kernel_symbol *start, *stop; const unsigned long *crcs; enum { NOT_GPL_ONLY, GPL_ONLY, WILL_BE_GPL_ONLY, } licence; bool unused; }; #endif /* LINUX_VERSION_CODE */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) /* c33fa9f5609e918824446ef9a75319d4a802f1f4 was after 2.6.25 */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) /* 2fff0a48416af891dce38fd425246e337831e0bb was after 2.6.19 */ static bool virtual_address_mapped(unsigned long addr) { char retval; return probe_kernel_address(addr, retval) != -EFAULT; } #else /* LINUX_VERSION_CODE < */ static bool virtual_address_mapped(unsigned long addr); #endif /* LINUX_VERSION_CODE */ static long probe_kernel_read(void *dst, void *src, size_t size) { if (size == 0) return 0; if (!virtual_address_mapped((unsigned long)src) || !virtual_address_mapped((unsigned long)src + size - 1)) return -EFAULT; memcpy(dst, src, size); return 0; } #endif /* LINUX_VERSION_CODE */ static LIST_HEAD(updates); #ifdef KSPLICE_STANDALONE #if defined(CONFIG_KSPLICE) || defined(CONFIG_KSPLICE_MODULE) extern struct list_head ksplice_modules; #else /* !CONFIG_KSPLICE */ LIST_HEAD(ksplice_modules); #endif /* CONFIG_KSPLICE */ #else /* !KSPLICE_STANDALONE */ LIST_HEAD(ksplice_modules); EXPORT_SYMBOL_GPL(ksplice_modules); static struct kobject *ksplice_kobj; #endif /* KSPLICE_STANDALONE */ static struct kobj_type update_ktype; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) /* Old kernels do not have kcalloc * e629946abd0bb8266e9c3d0fd1bff2ef8dec5443 was after 2.6.8 */ static void *kcalloc(size_t n, size_t size, typeof(GFP_KERNEL) flags) { char *mem; if (n != 0 && size > ULONG_MAX / n) return NULL; mem = kmalloc(n * size, flags); if (mem) memset(mem, 0, n * size); return mem; } #endif /* LINUX_VERSION_CODE */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12) /* 8c63b6d337534a6b5fb111dc27d0850f535118c0 was after 2.6.11 */ static void u32_swap(void *a, void *b, int size) { u32 t = *(u32 *)a; *(u32 *)a = *(u32 *)b; *(u32 *)b = t; } static void generic_swap(void *a, void *b, int size) { char t; do { t = *(char *)a; *(char *)a++ = *(char *)b; *(char *)b++ = t; } while (--size > 0); } /** * sort - sort an array of elements * @base: pointer to data to sort * @num: number of elements * @size: size of each element * @cmp: pointer to comparison function * @swap: pointer to swap function or NULL * * This function does a heapsort on the given array. You may provide a * swap function optimized to your element type. * * Sorting time is O(n log n) both on average and worst-case. While * qsort is about 20% faster on average, it suffers from exploitable * O(n*n) worst-case behavior and extra memory requirements that make * it less suitable for kernel use. */ void sort(void *base, size_t num, size_t size, int (*cmp)(const void *, const void *), void (*swap)(void *, void *, int size)) { /* pre-scale counters for performance */ int i = (num / 2 - 1) * size, n = num * size, c, r; if (!swap) swap = (size == 4 ? u32_swap : generic_swap); /* heapify */ for (; i >= 0; i -= size) { for (r = i; r * 2 + size < n; r = c) { c = r * 2 + size; if (c < n - size && cmp(base + c, base + c + size) < 0) c += size; if (cmp(base + r, base + c) >= 0) break; swap(base + r, base + c, size); } } /* sort */ for (i = n - size; i > 0; i -= size) { swap(base, base + i, size); for (r = 0; r * 2 + size < i; r = c) { c = r * 2 + size; if (c < i - size && cmp(base + c, base + c + size) < 0) c += size; if (cmp(base + r, base + c) >= 0) break; swap(base + r, base + c, size); } } } #endif /* LINUX_VERSION_CODE < */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) /* Old kernels do not have kstrdup * 543537bd922692bc978e2e356fcd8bfc9c2ee7d5 was after 2.6.12 */ #define kstrdup ksplice_kstrdup static char *kstrdup(const char *s, typeof(GFP_KERNEL) gfp) { size_t len; char *buf; if (!s) return NULL; len = strlen(s) + 1; buf = kmalloc(len, gfp); if (buf) memcpy(buf, s, len); return buf; } #endif /* LINUX_VERSION_CODE */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) /* Old kernels use semaphore instead of mutex * 97d1f15b7ef52c1e9c28dc48b454024bb53a5fd2 was after 2.6.16 */ #define mutex semaphore #define mutex_lock down #define mutex_unlock up #endif /* LINUX_VERSION_CODE */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) /* 11443ec7d9286dd25663516436a14edfb5f43857 was after 2.6.21 */ static char * __attribute_used__ kvasprintf(typeof(GFP_KERNEL) gfp, const char *fmt, va_list ap) { unsigned int len; char *p, dummy[1]; va_list aq; va_copy(aq, ap); len = vsnprintf(dummy, 0, fmt, aq); va_end(aq); p = kmalloc(len + 1, gfp); if (!p) return NULL; vsnprintf(p, len + 1, fmt, ap); return p; } #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) /* e905914f96e11862b130dd229f73045dad9a34e8 was after 2.6.17 */ static char * __attribute__((format (printf, 2, 3))) kasprintf(typeof(GFP_KERNEL) gfp, const char *fmt, ...) { va_list ap; char *p; va_start(ap, fmt); p = kvasprintf(gfp, fmt, ap); va_end(ap); return p; } #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) /* 06b2a76d25d3cfbd14680021c1d356c91be6904e was after 2.6.24 */ static int strict_strtoul(const char *cp, unsigned int base, unsigned long *res) { char *tail; unsigned long val; size_t len; *res = 0; len = strlen(cp); if (len == 0) return -EINVAL; val = simple_strtoul(cp, &tail, base); if ((*tail == '\0') || ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) { *res = val; return 0; } return -EINVAL; } #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) /* 9b1a4d38373a5581a4e01032a3ccdd94cd93477b was after 2.6.26 */ /* Assume cpus == NULL. */ #define stop_machine(fn, data, cpus) stop_machine_run(fn, data, NR_CPUS); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) /* ee527cd3a20c2aeaac17d939e5d011f7a76d69f5 was after 2.6.21 */ EXTRACT_SYMBOL(stop_machine_run); #endif /* LINUX_VERSION_CODE */ #endif /* LINUX_VERSION_CODE */ #ifndef task_thread_info #define task_thread_info(task) (task)->thread_info #endif /* !task_thread_info */ #ifdef KSPLICE_STANDALONE #ifdef do_each_thread_ve /* OpenVZ kernels define this */ #define do_each_thread do_each_thread_all #define while_each_thread while_each_thread_all #endif static bool bootstrapped = false; /* defined by ksplice-create */ extern const struct ksplice_reloc ksplice_init_relocs[], ksplice_init_relocs_end[]; #endif /* KSPLICE_STANDALONE */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) /* c6b37801911d7f4663c99cad8aa230bc934cea82 was after 2.6.29 */ extern struct list_head modules; EXTRACT_SYMBOL(modules); extern struct mutex module_mutex; EXTRACT_SYMBOL(module_mutex); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) && defined(CONFIG_UNUSED_SYMBOLS) /* f71d20e961474dde77e6558396efb93d6ac80a4b was after 2.6.17 */ #define KSPLICE_KSYMTAB_UNUSED_SUPPORT 1 #endif /* LINUX_VERSION_CODE */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) /* 9f28bb7e1d0188a993403ab39b774785892805e1 was after 2.6.16 */ #define KSPLICE_KSYMTAB_FUTURE_SUPPORT 1 #endif /* LINUX_VERSION_CODE */ extern const struct kernel_symbol __start___ksymtab[]; EXTRACT_SYMBOL(__start___ksymtab); extern const struct kernel_symbol __stop___ksymtab[]; EXTRACT_SYMBOL(__stop___ksymtab); extern const unsigned long __start___kcrctab[]; EXTRACT_SYMBOL(__start___kcrctab); extern const struct kernel_symbol __start___ksymtab_gpl[]; EXTRACT_SYMBOL(__start___ksymtab_gpl); extern const struct kernel_symbol __stop___ksymtab_gpl[]; EXTRACT_SYMBOL(__stop___ksymtab_gpl); extern const unsigned long __start___kcrctab_gpl[]; EXTRACT_SYMBOL(__start___kcrctab_gpl); #ifdef KSPLICE_KSYMTAB_UNUSED_SUPPORT extern const struct kernel_symbol __start___ksymtab_unused[]; EXTRACT_SYMBOL(__start___ksymtab_unused); extern const struct kernel_symbol __stop___ksymtab_unused[]; EXTRACT_SYMBOL(__stop___ksymtab_unused); extern const unsigned long __start___kcrctab_unused[]; EXTRACT_SYMBOL(__start___kcrctab_unused); extern const struct kernel_symbol __start___ksymtab_unused_gpl[]; EXTRACT_SYMBOL(__start___ksymtab_unused_gpl); extern const struct kernel_symbol __stop___ksymtab_unused_gpl[]; EXTRACT_SYMBOL(__stop___ksymtab_unused_gpl); extern const unsigned long __start___kcrctab_unused_gpl[]; EXTRACT_SYMBOL(__start___kcrctab_unused_gpl); #endif /* KSPLICE_KSYMTAB_UNUSED_SUPPORT */ #ifdef KSPLICE_KSYMTAB_FUTURE_SUPPORT extern const struct kernel_symbol __start___ksymtab_gpl_future[]; EXTRACT_SYMBOL(__start___ksymtab_gpl_future); extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; EXTRACT_SYMBOL(__stop___ksymtab_gpl_future); extern const unsigned long __start___kcrctab_gpl_future[]; EXTRACT_SYMBOL(__start___kcrctab_gpl_future); #endif /* KSPLICE_KSYMTAB_FUTURE_SUPPORT */ #endif /* LINUX_VERSION_CODE */ static struct update *init_ksplice_update(const char *kid); static void cleanup_ksplice_update(struct update *update); static void maybe_cleanup_ksplice_update(struct update *update); static void add_to_update(struct ksplice_mod_change *change, struct update *update); static int ksplice_sysfs_init(struct update *update); /* Preparing the relocations and patches for application */ static abort_t apply_update(struct update *update); static abort_t reverse_update(struct update *update); static abort_t prepare_change(struct ksplice_mod_change *change); static abort_t finalize_change(struct ksplice_mod_change *change); static abort_t finalize_patches(struct ksplice_mod_change *change); static abort_t add_dependency_on_address(struct ksplice_mod_change *change, unsigned long addr); static abort_t map_trampoline_pages(struct update *update); static void unmap_trampoline_pages(struct update *update); static void *map_writable(void *addr, size_t len); static abort_t apply_relocs(struct ksplice_mod_change *change, const struct ksplice_reloc *relocs, const struct ksplice_reloc *relocs_end); static abort_t apply_reloc(struct ksplice_mod_change *change, const struct ksplice_reloc *r); static abort_t apply_howto_reloc(struct ksplice_mod_change *change, const struct ksplice_reloc *r); static abort_t apply_howto_date(struct ksplice_mod_change *change, const struct ksplice_reloc *r); static abort_t read_reloc_value(struct ksplice_mod_change *change, const struct ksplice_reloc *r, unsigned long addr, unsigned long *valp); static abort_t write_reloc_value(struct ksplice_mod_change *change, const struct ksplice_reloc *r, unsigned long addr, unsigned long sym_addr); static abort_t create_module_list_entry(struct ksplice_mod_change *change, bool to_be_applied); static void cleanup_module_list_entries(struct update *update); static void __attribute__((noreturn)) ksplice_deleted(void); /* run-pre matching */ static abort_t match_change_sections(struct ksplice_mod_change *change, bool consider_data_sections); static abort_t find_section(struct ksplice_mod_change *change, struct ksplice_section *sect); static abort_t try_addr(struct ksplice_mod_change *change, struct ksplice_section *sect, unsigned long run_addr, struct list_head *safety_records, enum run_pre_mode mode); static abort_t run_pre_cmp(struct ksplice_mod_change *change, const struct ksplice_section *sect, unsigned long run_addr, struct list_head *safety_records, enum run_pre_mode mode); #ifndef CONFIG_FUNCTION_DATA_SECTIONS /* defined in arch/ARCH/kernel/ksplice-arch.c */ static abort_t arch_run_pre_cmp(struct ksplice_mod_change *change, struct ksplice_section *sect, unsigned long run_addr, struct list_head *safety_records, enum run_pre_mode mode); #endif /* CONFIG_FUNCTION_DATA_SECTIONS */ static void print_bytes(struct ksplice_mod_change *change, const unsigned char *run, int runc, const unsigned char *pre, int prec); #if defined(KSPLICE_STANDALONE) && !defined(CONFIG_KALLSYMS) static abort_t brute_search(struct ksplice_mod_change *change, struct ksplice_section *sect, const void *start, unsigned long len, struct list_head *vals); static abort_t brute_search_all(struct ksplice_mod_change *change, struct ksplice_section *sect, struct list_head *vals); #endif /* KSPLICE_STANDALONE && !CONFIG_KALLSYMS */ static const struct ksplice_reloc * init_reloc_search(struct ksplice_mod_change *change, const struct ksplice_section *sect); static const struct ksplice_reloc *find_reloc(const struct ksplice_reloc *start, const struct ksplice_reloc *end, unsigned long address, unsigned long size); static abort_t lookup_reloc(struct ksplice_mod_change *change, const struct ksplice_reloc **fingerp, unsigned long addr, const struct ksplice_reloc **relocp); static abort_t handle_reloc(struct ksplice_mod_change *change, const struct ksplice_section *sect, const struct ksplice_reloc *r, unsigned long run_addr, enum run_pre_mode mode); static abort_t handle_howto_date(struct ksplice_mod_change *change, const struct ksplice_section *sect, const struct ksplice_reloc *r, unsigned long run_addr, enum run_pre_mode mode); static abort_t handle_howto_reloc(struct ksplice_mod_change *change, const struct ksplice_section *sect, const struct ksplice_reloc *r, unsigned long run_addr, enum run_pre_mode mode); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) #ifdef CONFIG_BUG static abort_t handle_bug(struct ksplice_mod_change *change, const struct ksplice_reloc *r, unsigned long run_addr); #endif /* CONFIG_BUG */ #else /* LINUX_VERSION_CODE < */ /* 7664c5a1da4711bb6383117f51b94c8dc8f3f1cd was after 2.6.19 */ #endif /* LINUX_VERSION_CODE */ static abort_t handle_extable(struct ksplice_mod_change *change, const struct ksplice_reloc *r, unsigned long run_addr); static struct ksplice_section *symbol_section(struct ksplice_mod_change *change, const struct ksplice_symbol *sym); static int compare_section_labels(const void *va, const void *vb); static int symbol_section_bsearch_compare(const void *a, const void *b); static const struct ksplice_reloc * patch_reloc(struct ksplice_mod_change *change, const struct ksplice_patch *p); /* Computing possible addresses for symbols */ static abort_t lookup_symbol(struct ksplice_mod_change *change, const struct ksplice_symbol *ksym, struct list_head *vals); static void cleanup_symbol_arrays(struct ksplice_mod_change *change); static abort_t init_symbol_arrays(struct ksplice_mod_change *change); static abort_t init_symbol_array(struct ksplice_mod_change *change, struct ksplice_symbol *start, struct ksplice_symbol *end); static abort_t uniquify_symbols(struct ksplice_mod_change *change); static abort_t add_matching_values(struct ksplice_lookup *lookup, const char *sym_name, unsigned long sym_val); static bool add_export_values(const struct symsearch *syms, struct module *owner, unsigned int symnum, void *data); static int symbolp_bsearch_compare(const void *key, const void *elt); static int compare_symbolp_names(const void *a, const void *b); static int compare_symbolp_labels(const void *a, const void *b); #ifdef CONFIG_KALLSYMS static int add_kallsyms_values(void *data, const char *name, struct module *owner, unsigned long val); #endif /* CONFIG_KALLSYMS */ #ifdef KSPLICE_STANDALONE static abort_t add_system_map_candidates(struct ksplice_mod_change *change, const struct ksplice_system_map *start, const struct ksplice_system_map *end, const char *label, struct list_head *vals); static int compare_system_map(const void *a, const void *b); static int system_map_bsearch_compare(const void *key, const void *elt); #endif /* KSPLICE_STANDALONE */ static abort_t new_export_lookup(struct ksplice_mod_change *ichange, const char *name, struct list_head *vals); /* Atomic update trampoline insertion and removal */ static abort_t patch_action(struct update *update, enum ksplice_action action); static int __apply_patches(void *update); static int __reverse_patches(void *update); static abort_t check_each_task(struct update *update); static abort_t check_task(struct update *update, const struct task_struct *t, bool rerun); static abort_t check_stack(struct update *update, struct conflict *conf, const struct thread_info *tinfo, const unsigned long *stack); static abort_t check_address(struct update *update, struct conflict *conf, unsigned long addr); static abort_t check_record(struct conflict_addr *ca, const struct safety_record *rec, unsigned long addr); static bool is_stop_machine(const struct task_struct *t); static void cleanup_conflicts(struct update *update); static void print_conflicts(struct update *update); static void insert_trampoline(struct ksplice_patch *p); static abort_t verify_trampoline(struct ksplice_mod_change *change, const struct ksplice_patch *p); static void remove_trampoline(const struct ksplice_patch *p); static abort_t create_labelval(struct ksplice_mod_change *change, struct ksplice_symbol *ksym, unsigned long val, int status); static abort_t create_safety_record(struct ksplice_mod_change *change, const struct ksplice_section *sect, struct list_head *record_list, unsigned long run_addr, unsigned long run_size); static abort_t add_candidate_val(struct ksplice_mod_change *change, struct list_head *vals, unsigned long val); static void release_vals(struct list_head *vals); static void set_temp_labelvals(struct ksplice_mod_change *change, int status); static int contains_canary(struct ksplice_mod_change *change, unsigned long blank_addr, const struct ksplice_reloc_howto *howto); static unsigned long follow_trampolines(struct ksplice_mod_change *change, unsigned long addr); static bool patches_module(const struct module *a, const struct module *b); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) /* 66f92cf9d415e96a5bdd6c64de8dd8418595d2fc was after 2.6.29 */ static bool strstarts(const char *str, const char *prefix); #endif /* LINUX_VERSION_CODE */ static bool singular(struct list_head *list); static void *bsearch(const void *key, const void *base, size_t n, size_t size, int (*cmp)(const void *key, const void *elt)); static int compare_relocs(const void *a, const void *b); static int reloc_bsearch_compare(const void *key, const void *elt); /* Debugging */ static abort_t init_debug_buf(struct update *update); static void clear_debug_buf(struct update *update); static int __attribute__((format(printf, 2, 3))) _ksdebug(struct update *update, const char *fmt, ...); #define ksdebug(change, fmt, ...) \ _ksdebug(change->update, fmt, ## __VA_ARGS__) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) && defined(CONFIG_KALLSYMS) /* 75a66614db21007bcc8c37f9c5d5b922981387b9 was after 2.6.29 */ static int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *, unsigned long), void *data); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) static unsigned int kallsyms_expand_symbol(unsigned int off, char *result); #endif /* LINUX_VERSION_CODE */ static int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *, unsigned long), void *data); #endif /* LINUX_VERSION_CODE && CONFIG_KALLSYMS */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) /* c6b37801911d7f4663c99cad8aa230bc934cea82 was after 2.6.29 */ static struct module *find_module(const char *name); static int use_module(struct module *a, struct module *b); static const struct kernel_symbol *find_symbol(const char *name, struct module **owner, const unsigned long **crc, bool gplok, bool warn); static bool each_symbol(bool (*fn)(const struct symsearch *arr, struct module *owner, unsigned int symnum, void *data), void *data); static struct module *__module_address(unsigned long addr); #endif /* LINUX_VERSION_CODE */ /* Architecture-specific functions defined in arch/ARCH/kernel/ksplice-arch.c */ /* Prepare a trampoline for the given patch */ static abort_t prepare_trampoline(struct ksplice_mod_change *change, struct ksplice_patch *p); /* What address does the trampoline at addr jump to? */ static abort_t trampoline_target(struct ksplice_mod_change *change, unsigned long addr, unsigned long *new_addr); /* Hook to handle pc-relative jumps inserted by parainstructions */ static abort_t handle_paravirt(struct ksplice_mod_change *change, unsigned long pre, unsigned long run, int *matched); /* Is address p on the stack of the given thread? */ static bool valid_stack_ptr(const struct thread_info *tinfo, const void *p); #ifndef KSPLICE_STANDALONE #include "ksplice-arch.c" #elif defined CONFIG_X86 #include "x86/ksplice-arch.c" #elif defined CONFIG_ARM #include "arm/ksplice-arch.c" #endif /* KSPLICE_STANDALONE */ #define clear_list(head, type, member) \ do { \ struct list_head *_pos, *_n; \ list_for_each_safe(_pos, _n, head) { \ list_del(_pos); \ kfree(list_entry(_pos, type, member)); \ } \ } while (0) /** * init_ksplice_mod_change() - Initializes a ksplice change * @change: The change to be initialized. All of the public fields of the * change and its associated data structures should be populated * before this function is called. The values of the private * fields will be ignored. **/ int init_ksplice_mod_change(struct ksplice_mod_change *change) { struct update *update; struct ksplice_patch *p; struct ksplice_section *s; int ret = 0; #ifdef KSPLICE_STANDALONE if (!bootstrapped) return -1; #endif /* KSPLICE_STANDALONE */ INIT_LIST_HEAD(&change->temp_labelvals); INIT_LIST_HEAD(&change->safety_records); sort(change->old_code.relocs, change->old_code.relocs_end - change->old_code.relocs, sizeof(*change->old_code.relocs), compare_relocs, NULL); sort(change->new_code.relocs, change->new_code.relocs_end - change->new_code.relocs, sizeof(*change->new_code.relocs), compare_relocs, NULL); sort(change->old_code.sections, change->old_code.sections_end - change->old_code.sections, sizeof(*change->old_code.sections), compare_section_labels, NULL); #ifdef KSPLICE_STANDALONE sort(change->new_code.system_map, change->new_code.system_map_end - change->new_code.system_map, sizeof(*change->new_code.system_map), compare_system_map, NULL); sort(change->old_code.system_map, change->old_code.system_map_end - change->old_code.system_map, sizeof(*change->old_code.system_map), compare_system_map, NULL); #endif /* KSPLICE_STANDALONE */ for (p = change->patches; p < change->patches_end; p++) p->vaddr = NULL; for (s = change->old_code.sections; s < change->old_code.sections_end; s++) s->match_map = NULL; for (p = change->patches; p < change->patches_end; p++) { const struct ksplice_reloc *r = patch_reloc(change, p); if (r == NULL) return -ENOENT; if (p->type == KSPLICE_PATCH_DATA) { s = symbol_section(change, r->symbol); if (s == NULL) return -ENOENT; /* Ksplice creates KSPLICE_PATCH_DATA patches in order * to modify rodata sections that have been explicitly * marked for patching using the ksplice-patch.h macro * ksplice_assume_rodata. Here we modify the section * flags appropriately. */ if (s->flags & KSPLICE_SECTION_DATA) s->flags = (s->flags & ~KSPLICE_SECTION_DATA) | KSPLICE_SECTION_RODATA; } } mutex_lock(&module_mutex); list_for_each_entry(update, &updates, list) { if (strcmp(change->kid, update->kid) == 0) { if (update->stage != STAGE_PREPARING) { ret = -EPERM; goto out; } add_to_update(change, update); ret = 0; goto out; } } update = init_ksplice_update(change->kid); if (update == NULL) { ret = -ENOMEM; goto out; } ret = ksplice_sysfs_init(update); if (ret != 0) { cleanup_ksplice_update(update); goto out; } add_to_update(change, update); out: mutex_unlock(&module_mutex); return ret; } EXPORT_SYMBOL_GPL(init_ksplice_mod_change); /** * cleanup_ksplice_mod_change() - Cleans up a change if appropriate * @change: The change to be cleaned up * * cleanup_ksplice_mod_change is ordinarily called twice for each * Ksplice update: once when the old_code module is unloaded, and once * when the new_code module is unloaded. By freeing what can be freed * on each unload, we avoid leaks even in unusual scenarios, e.g. if * several alternative old_code modules are loaded and unloaded * successively. */ void cleanup_ksplice_mod_change(struct ksplice_mod_change *change) { if (change->update == NULL) return; mutex_lock(&module_mutex); if (change->update->stage == STAGE_APPLIED) { struct ksplice_mod_change *c; bool found = false; list_for_each_entry(c, &change->update->unused_changes, list) { if (c == change) found = true; } if (found) list_del(&change->list); mutex_unlock(&module_mutex); return; } list_del(&change->list); if (change->update->stage == STAGE_PREPARING) maybe_cleanup_ksplice_update(change->update); change->update = NULL; mutex_unlock(&module_mutex); } EXPORT_SYMBOL_GPL(cleanup_ksplice_mod_change); static struct update *init_ksplice_update(const char *kid) { struct update *update; update = kcalloc(1, sizeof(struct update), GFP_KERNEL); if (update == NULL) return NULL; update->name = kasprintf(GFP_KERNEL, "ksplice_%s", kid); if (update->name == NULL) { kfree(update); return NULL; } update->kid = kstrdup(kid, GFP_KERNEL); if (update->kid == NULL) { kfree(update->name); kfree(update); return NULL; } if (try_module_get(THIS_MODULE) != 1) { kfree(update->kid); kfree(update->name); kfree(update); return NULL; } INIT_LIST_HEAD(&update->changes); INIT_LIST_HEAD(&update->unused_changes); INIT_LIST_HEAD(&update->ksplice_module_list); if (init_debug_buf(update) != OK) { module_put(THIS_MODULE); kfree(update->kid); kfree(update->name); kfree(update); return NULL; } list_add(&update->list, &updates); update->stage = STAGE_PREPARING; update->abort_cause = OK; update->partial = 0; INIT_LIST_HEAD(&update->conflicts); return update; } static void cleanup_ksplice_update(struct update *update) { list_del(&update->list); cleanup_conflicts(update); clear_debug_buf(update); cleanup_module_list_entries(update); kfree(update->kid); kfree(update->name); kfree(update); module_put(THIS_MODULE); } /* Clean up the update if it no longer has any changes */ static void maybe_cleanup_ksplice_update(struct update *update) { if (list_empty(&update->changes) && list_empty(&update->unused_changes)) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) kobject_put(&update->kobj); #else /* LINUX_VERSION_CODE < */ /* 6d06adfaf82d154023141ddc0c9de18b6a49090b was after 2.6.24 */ kobject_unregister(&update->kobj); #endif /* LINUX_VERSION_CODE */ } static void add_to_update(struct ksplice_mod_change *change, struct update *update) { change->update = update; list_add(&change->list, &update->unused_changes); } static int ksplice_sysfs_init(struct update *update) { int ret = 0; memset(&update->kobj, 0, sizeof(update->kobj)); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) #ifndef KSPLICE_STANDALONE ret = kobject_init_and_add(&update->kobj, &update_ktype, ksplice_kobj, "%s", update->kid); #else /* KSPLICE_STANDALONE */ ret = kobject_init_and_add(&update->kobj, &update_ktype, &THIS_MODULE->mkobj.kobj, "ksplice"); #endif /* KSPLICE_STANDALONE */ #else /* LINUX_VERSION_CODE < */ /* 6d06adfaf82d154023141ddc0c9de18b6a49090b was after 2.6.24 */ ret = kobject_set_name(&update->kobj, "%s", "ksplice"); if (ret != 0) return ret; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) update->kobj.parent = &THIS_MODULE->mkobj.kobj; #else /* LINUX_VERSION_CODE < */ /* b86ab02803095190d6b72bcc18dcf620bf378df9 was after 2.6.10 */ update->kobj.parent = &THIS_MODULE->mkobj->kobj; #endif /* LINUX_VERSION_CODE */ update->kobj.ktype = &update_ktype; ret = kobject_register(&update->kobj); #endif /* LINUX_VERSION_CODE */ if (ret != 0) return ret; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) kobject_uevent(&update->kobj, KOBJ_ADD); #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) /* 312c004d36ce6c739512bac83b452f4c20ab1f62 was after 2.6.14 */ /* 12025235884570ba7f02a6f427f973ac6be7ec54 was after 2.6.9 */ kobject_uevent(&update->kobj, KOBJ_ADD, NULL); #endif /* LINUX_VERSION_CODE */ return 0; } #ifdef KSPLICE_NEED_PARAINSTRUCTIONS EXTRACT_SYMBOL(apply_paravirt); #endif /* KSPLICE_NEED_PARAINSTRUCTIONS */ static abort_t apply_update(struct update *update) { struct ksplice_mod_change *change, *n; abort_t ret; int retval; list_for_each_entry(change, &update->changes, list) { ret = create_module_list_entry(change, true); if (ret != OK) goto out; } list_for_each_entry_safe(change, n, &update->unused_changes, list) { if (strcmp(change->target_name, "vmlinux") == 0) { change->target = NULL; } else if (change->target == NULL) { change->target = find_module(change->target_name); if (change->target == NULL || !module_is_live(change->target)) { if (!update->partial) { ret = TARGET_NOT_LOADED; goto out; } ret = create_module_list_entry(change, false); if (ret != OK) goto out; continue; } retval = use_module(change->new_code_mod, change->target); if (retval != 1) { ret = UNEXPECTED; goto out; } } ret = create_module_list_entry(change, true); if (ret != OK) goto out; list_del(&change->list); list_add_tail(&change->list, &update->changes); #ifdef KSPLICE_NEED_PARAINSTRUCTIONS if (change->target == NULL) { apply_paravirt(change->new_code.parainstructions, change->new_code.parainstructions_end); apply_paravirt(change->old_code.parainstructions, change->old_code.parainstructions_end); } #endif /* KSPLICE_NEED_PARAINSTRUCTIONS */ } list_for_each_entry(change, &update->changes, list) { const struct ksplice_section *sect; for (sect = change->new_code.sections; sect < change->new_code.sections_end; sect++) { struct safety_record *rec = kmalloc(sizeof(*rec), GFP_KERNEL); if (rec == NULL) { ret = OUT_OF_MEMORY; goto out; } rec->addr = sect->address; rec->size = sect->size; rec->label = sect->symbol->label; list_add(&rec->list, &change->safety_records); } } list_for_each_entry(change, &update->changes, list) { ret = init_symbol_arrays(change); if (ret != OK) { cleanup_symbol_arrays(change); goto out; } ret = prepare_change(change); cleanup_symbol_arrays(change); if (ret != OK) goto out; } ret = patch_action(update, KS_APPLY); out: list_for_each_entry(change, &update->changes, list) { struct ksplice_section *s; if (update->stage == STAGE_PREPARING) clear_list(&change->safety_records, struct safety_record, list); for (s = change->old_code.sections; s < change->old_code.sections_end; s++) { if (s->match_map != NULL) { vfree(s->match_map); s->match_map = NULL; } s->flags &= ~KSPLICE_SECTION_MATCHED; } } if (update->stage == STAGE_PREPARING) cleanup_module_list_entries(update); if (ret == OK) printk(KERN_INFO "ksplice: Update %s applied successfully\n", update->kid); return ret; } static abort_t reverse_update(struct update *update) { abort_t ret; struct ksplice_mod_change *change; clear_debug_buf(update); ret = init_debug_buf(update); if (ret != OK) return ret; _ksdebug(update, "Preparing to reverse %s\n", update->kid); ret = patch_action(update, KS_REVERSE); if (ret != OK) return ret; list_for_each_entry(change, &update->changes, list) clear_list(&change->safety_records, struct safety_record, list); printk(KERN_INFO "ksplice: Update %s reversed successfully\n", update->kid); return OK; } static int compare_symbolp_names(const void *a, const void *b) { const struct ksplice_symbol *const *sympa = a, *const *sympb = b; if ((*sympa)->name == NULL && (*sympb)->name == NULL) return 0; if ((*sympa)->name == NULL) return -1; if ((*sympb)->name == NULL) return 1; return strcmp((*sympa)->name, (*sympb)->name); } static int compare_symbolp_labels(const void *a, const void *b) { const struct ksplice_symbol *const *sympa = a, *const *sympb = b; return strcmp((*sympa)->label, (*sympb)->label); } static int symbolp_bsearch_compare(const void *key, const void *elt) { const char *name = key; const struct ksplice_symbol *const *symp = elt; const struct ksplice_symbol *sym = *symp; if (sym->name == NULL) return 1; return strcmp(name, sym->name); } static abort_t add_matching_values(struct ksplice_lookup *lookup, const char *sym_name, unsigned long sym_val) { struct ksplice_symbol **symp; abort_t ret; symp = bsearch(sym_name, lookup->arr, lookup->size, sizeof(*lookup->arr), symbolp_bsearch_compare); if (symp == NULL) return OK; while (symp > lookup->arr && symbolp_bsearch_compare(sym_name, symp - 1) == 0) symp--; for (; symp < lookup->arr + lookup->size; symp++) { struct ksplice_symbol *sym = *symp; if (sym->name == NULL || strcmp(sym_name, sym->name) != 0) break; ret = add_candidate_val(lookup->change, sym->candidate_vals, sym_val); if (ret != OK) return ret; } return OK; } #ifdef CONFIG_KALLSYMS static int add_kallsyms_values(void *data, const char *name, struct module *owner, unsigned long val) { struct ksplice_lookup *lookup = data; if (owner == lookup->change->new_code_mod || !patches_module(owner, lookup->change->target)) return (__force int)OK; return (__force int)add_matching_values(lookup, name, val); } #endif /* CONFIG_KALLSYMS */ static bool add_export_values(const struct symsearch *syms, struct module *owner, unsigned int symnum, void *data) { struct ksplice_lookup *lookup = data; abort_t ret; ret = add_matching_values(lookup, syms->start[symnum].name, syms->start[symnum].value); if (ret != OK) { lookup->ret = ret; return true; } return false; } static void cleanup_symbol_arrays(struct ksplice_mod_change *change) { struct ksplice_symbol *sym; for (sym = change->new_code.symbols; sym < change->new_code.symbols_end; sym++) { if (sym->candidate_vals != NULL) { clear_list(sym->candidate_vals, struct candidate_val, list); kfree(sym->candidate_vals); sym->candidate_vals = NULL; } } for (sym = change->old_code.symbols; sym < change->old_code.symbols_end; sym++) { if (sym->candidate_vals != NULL) { clear_list(sym->candidate_vals, struct candidate_val, list); kfree(sym->candidate_vals); sym->candidate_vals = NULL; } } } /* * The new_code and old_code modules each have their own independent * ksplice_symbol structures. uniquify_symbols unifies these separate * pieces of kernel symbol information by replacing all references to * the old_code copy of symbols with references to the new_code copy. */ static abort_t uniquify_symbols(struct ksplice_mod_change *change) { struct ksplice_reloc *r; struct ksplice_section *s; struct ksplice_symbol *sym, **sym_arr, **symp; size_t size = change->new_code.symbols_end - change->new_code.symbols; if (size == 0) return OK; sym_arr = vmalloc(sizeof(*sym_arr) * size); if (sym_arr == NULL) return OUT_OF_MEMORY; for (symp = sym_arr, sym = change->new_code.symbols; symp < sym_arr + size && sym < change->new_code.symbols_end; sym++, symp++) *symp = sym; sort(sym_arr, size, sizeof(*sym_arr), compare_symbolp_labels, NULL); for (r = change->old_code.relocs; r < change->old_code.relocs_end; r++) { symp = bsearch(&r->symbol, sym_arr, size, sizeof(*sym_arr), compare_symbolp_labels); if (symp != NULL) { if ((*symp)->name == NULL) (*symp)->name = r->symbol->name; r->symbol = *symp; } } for (s = change->old_code.sections; s < change->old_code.sections_end; s++) { symp = bsearch(&s->symbol, sym_arr, size, sizeof(*sym_arr), compare_symbolp_labels); if (symp != NULL) { if ((*symp)->name == NULL) (*symp)->name = s->symbol->name; s->symbol = *symp; } } vfree(sym_arr); return OK; } /* * Initialize the ksplice_symbol structures in the given array using * the kallsyms and exported symbol tables. */ static abort_t init_symbol_array(struct ksplice_mod_change *change, struct ksplice_symbol *start, struct ksplice_symbol *end) { struct ksplice_symbol *sym, **sym_arr, **symp; struct ksplice_lookup lookup; size_t size = end - start; abort_t ret; if (size == 0) return OK; for (sym = start; sym < end; sym++) { if (strstarts(sym->label, "__ksymtab")) { const struct kernel_symbol *ksym; const char *colon = strchr(sym->label, ':'); const char *name = colon + 1; if (colon == NULL) continue; ksym = find_symbol(name, NULL, NULL, true, false); if (ksym == NULL) { ksdebug(change, "Could not find kernel_symbol " "structure for %s\n", name); continue; } sym->value = (unsigned long)ksym; sym->candidate_vals = NULL; continue; } sym->candidate_vals = kmalloc(sizeof(*sym->candidate_vals), GFP_KERNEL); if (sym->candidate_vals == NULL) return OUT_OF_MEMORY; INIT_LIST_HEAD(sym->candidate_vals); sym->value = 0; } sym_arr = vmalloc(sizeof(*sym_arr) * size); if (sym_arr == NULL) return OUT_OF_MEMORY; for (symp = sym_arr, sym = start; symp < sym_arr + size && sym < end; sym++, symp++) *symp = sym; sort(sym_arr, size, sizeof(*sym_arr), compare_symbolp_names, NULL); lookup.change = change; lookup.arr = sym_arr; lookup.size = size; lookup.ret = OK; each_symbol(add_export_values, &lookup); ret = lookup.ret; #ifdef CONFIG_KALLSYMS if (ret == OK) ret = (__force abort_t) kallsyms_on_each_symbol(add_kallsyms_values, &lookup); #endif /* CONFIG_KALLSYMS */ vfree(sym_arr); return ret; } /* * Prepare the change's ksplice_symbol structures for run-pre matching * * noinline to prevent garbage on the stack from confusing check_stack */ static noinline abort_t init_symbol_arrays(struct ksplice_mod_change *change) { abort_t ret; ret = uniquify_symbols(change); if (ret != OK) return ret; ret = init_symbol_array(change, change->old_code.symbols, change->old_code.symbols_end); if (ret != OK) return ret; ret = init_symbol_array(change, change->new_code.symbols, change->new_code.symbols_end); if (ret != OK) return ret; return OK; } /* noinline to prevent garbage on the stack from confusing check_stack */ static noinline abort_t prepare_change(struct ksplice_mod_change *change) { abort_t ret; ksdebug(change, "Preparing and checking %s\n", change->name); ret = match_change_sections(change, false); if (ret == NO_MATCH) { /* It is possible that by using relocations from .data sections * we can successfully run-pre match the rest of the sections. * To avoid using any symbols obtained from .data sections * (which may be unreliable) in the post code, we first prepare * the post code and then try to run-pre match the remaining * sections with the help of .data sections. */ ksdebug(change, "Continuing without some sections; we might " "find them later.\n"); ret = finalize_change(change); if (ret != OK) { ksdebug(change, "Aborted. Unable to continue without " "the unmatched sections.\n"); return ret; } ksdebug(change, "run-pre: Considering .data sections to find " "the unmatched sections\n"); ret = match_change_sections(change, true); if (ret != OK) return ret; ksdebug(change, "run-pre: Found all previously unmatched " "sections\n"); return OK; } else if (ret != OK) { return ret; } return finalize_change(change); } /* * Finish preparing the change for insertion into the kernel. * Afterwards, the replacement code should be ready to run and the * ksplice_patches should all be ready for trampoline insertion. */ static abort_t finalize_change(struct ksplice_mod_change *change) { abort_t ret; ret = apply_relocs(change, change->new_code.relocs, change->new_code.relocs_end); if (ret != OK) return ret; ret = finalize_patches(change); if (ret != OK) return ret; return OK; } static abort_t finalize_patches(struct ksplice_mod_change *change) { struct ksplice_patch *p; struct safety_record *rec; abort_t ret; for (p = change->patches; p < change->patches_end; p++) { bool found = false; list_for_each_entry(rec, &change->safety_records, list) { if (rec->addr <= p->oldaddr && p->oldaddr < rec->addr + rec->size) { found = true; break; } } if (!found && p->type != KSPLICE_PATCH_EXPORT) { const struct ksplice_reloc *r = patch_reloc(change, p); if (r == NULL) { ksdebug(change, "A patch with no reloc at its " "oldaddr has no safety record\n"); return NO_MATCH; } ksdebug(change, "No safety record for patch with " "oldaddr %s+%lx\n", r->symbol->label, r->target_addend); return NO_MATCH; } if (p->type == KSPLICE_PATCH_TEXT) { ret = prepare_trampoline(change, p); if (ret != OK) return ret; } if (found && rec->addr + rec->size < p->oldaddr + p->size) { ksdebug(change, "Safety record %s is too short for " "patch\n", rec->label); return UNEXPECTED; } if (p->type == KSPLICE_PATCH_TEXT) { if (p->repladdr == 0) p->repladdr = (unsigned long)ksplice_deleted; } } for (p = change->patches; p < change->patches_end; p++) { struct ksplice_patch *q; for (q = change->patches; q < change->patches_end; q++) { if (p != q && p->oldaddr <= q->oldaddr && p->oldaddr + p->size > q->oldaddr) { ksdebug(change, "Overlapping oldaddrs " "for patches\n"); return UNEXPECTED; } } } return OK; } /* noinline to prevent garbage on the stack from confusing check_stack */ static noinline abort_t map_trampoline_pages(struct update *update) { struct ksplice_mod_change *change; list_for_each_entry(change, &update->changes, list) { struct ksplice_patch *p; for (p = change->patches; p < change->patches_end; p++) { p->vaddr = map_writable((void *)p->oldaddr, p->size); if (p->vaddr == NULL) { ksdebug(change, "Unable to map oldaddr read/write\n"); unmap_trampoline_pages(update); return UNEXPECTED; } } } return OK; } static void unmap_trampoline_pages(struct update *update) { struct ksplice_mod_change *change; list_for_each_entry(change, &update->changes, list) { struct ksplice_patch *p; for (p = change->patches; p < change->patches_end; p++) { vunmap((void *)((unsigned long)p->vaddr & PAGE_MASK)); p->vaddr = NULL; } } } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) && defined(CONFIG_X86_64) /* e3ebadd95cb621e2c7436f3d3646447ac9d5c16d was after 2.6.21 */ #define phys_base ({EXTRACT_SYMBOL(phys_base); phys_base;}) #endif /* LINUX_VERSION_CODE && CONFIG_X86_64 */ /* * map_writable creates a shadow page mapping of the range * [addr, addr + len) so that we can write to code mapped read-only. * * It is similar to a generalized version of x86's text_poke. But * because one cannot use vmalloc/vfree() inside stop_machine, we use * map_writable to map the pages before stop_machine, then use the * mapping inside stop_machine, and unmap the pages afterwards. */ static void *map_writable(void *addr, size_t len) { void *vaddr; int nr_pages = DIV_ROUND_UP(offset_in_page(addr) + len, PAGE_SIZE); struct page **pages = kmalloc(nr_pages * sizeof(*pages), GFP_KERNEL); void *page_addr = (void *)((unsigned long)addr & PAGE_MASK); int i; if (pages == NULL) return NULL; for (i = 0; i < nr_pages; i++) { if (__module_address((unsigned long)page_addr) == NULL) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) || !defined(CONFIG_X86_64) pages[i] = virt_to_page(page_addr); #else /* LINUX_VERSION_CODE < && CONFIG_X86_64 */ /* e3ebadd95cb621e2c7436f3d3646447ac9d5c16d was after 2.6.21 * This works around a broken virt_to_page() from the RHEL 5 backport * of x86-64 relocatable kernel support. */ pages[i] = pfn_to_page(__pa_symbol(page_addr) >> PAGE_SHIFT); #endif /* LINUX_VERSION_CODE || !CONFIG_X86_64 */ WARN_ON(!PageReserved(pages[i])); } else { pages[i] = vmalloc_to_page(addr); } if (pages[i] == NULL) { kfree(pages); return NULL; } page_addr += PAGE_SIZE; } vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL); kfree(pages); if (vaddr == NULL) return NULL; return vaddr + offset_in_page(addr); } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) /* c6b37801911d7f4663c99cad8aa230bc934cea82 was after 2.6.29 */ EXTRACT_SYMBOL(__module_text_address); #endif /* LINUX_VERSION_CODE */ /* * Ksplice adds a dependency on any symbol address used to resolve * relocations in the new_code module. * * Be careful to follow_trampolines so that we always depend on the * latest version of the target function, since that's the code that * will run if we call addr. */ static abort_t add_dependency_on_address(struct ksplice_mod_change *change, unsigned long addr) { struct ksplice_mod_change *c; struct module *m = __module_text_address(follow_trampolines(change, addr)); if (m == NULL) return OK; list_for_each_entry(c, &change->update->changes, list) { if (m == c->new_code_mod) return OK; } if (use_module(change->new_code_mod, m) != 1) return MODULE_BUSY; return OK; } static abort_t apply_relocs(struct ksplice_mod_change *change, const struct ksplice_reloc *relocs, const struct ksplice_reloc *relocs_end) { const struct ksplice_reloc *r; for (r = relocs; r < relocs_end; r++) { abort_t ret = apply_reloc(change, r); if (ret != OK) return ret; } return OK; } static abort_t apply_reloc(struct ksplice_mod_change *change, const struct ksplice_reloc *r) { switch (r->howto->type) { case KSPLICE_HOWTO_RELOC: case KSPLICE_HOWTO_RELOC_PATCH: return apply_howto_reloc(change, r); case KSPLICE_HOWTO_DATE: case KSPLICE_HOWTO_TIME: return apply_howto_date(change, r); default: ksdebug(change, "Unexpected howto type %d\n", r->howto->type); return UNEXPECTED; } } /* * Applies a relocation. Aborts if the symbol referenced in it has * not been uniquely resolved. */ static abort_t apply_howto_reloc(struct ksplice_mod_change *change, const struct ksplice_reloc *r) { abort_t ret; int canary_ret; unsigned long sym_addr; LIST_HEAD(vals); canary_ret = contains_canary(change, r->blank_addr, r->howto); if (canary_ret < 0) return UNEXPECTED; if (canary_ret == 0) { ksdebug(change, "reloc: skipped %lx to %s+%lx (altinstr)\n", r->blank_addr, r->symbol->label, r->target_addend); return OK; } #ifdef KSPLICE_STANDALONE if (!bootstrapped) { ret = add_system_map_candidates(change, change->new_code.system_map, change->new_code.system_map_end, r->symbol->label, &vals); if (ret != OK) { release_vals(&vals); return ret; } } #endif /* KSPLICE_STANDALONE */ ret = lookup_symbol(change, r->symbol, &vals); if (ret != OK) { release_vals(&vals); return ret; } /* * Relocations for the oldaddr fields of patches must have * been resolved via run-pre matching. */ if (!singular(&vals) || (r->symbol->candidate_vals != NULL && r->howto->type == KSPLICE_HOWTO_RELOC_PATCH)) { release_vals(&vals); ksdebug(change, "Failed to find %s for reloc\n", r->symbol->label); return FAILED_TO_FIND; } sym_addr = list_entry(vals.next, struct candidate_val, list)->val; release_vals(&vals); ret = write_reloc_value(change, r, r->blank_addr, r->howto->pcrel ? sym_addr - r->blank_addr : sym_addr); if (ret != OK) return ret; ksdebug(change, "reloc: %lx to %s+%lx (S=%lx ", r->blank_addr, r->symbol->label, r->target_addend, sym_addr); switch (r->howto->size) { case 1: ksdebug(change, "aft=%02x)\n", *(uint8_t *)r->blank_addr); break; case 2: ksdebug(change, "aft=%04x)\n", *(uint16_t *)r->blank_addr); break; case 4: ksdebug(change, "aft=%08x)\n", *(uint32_t *)r->blank_addr); break; #if BITS_PER_LONG >= 64 case 8: ksdebug(change, "aft=%016llx)\n", *(uint64_t *)r->blank_addr); break; #endif /* BITS_PER_LONG */ default: ksdebug(change, "Aborted. Invalid relocation size.\n"); return UNEXPECTED; } #ifdef KSPLICE_STANDALONE if (!bootstrapped) return OK; #endif /* KSPLICE_STANDALONE */ /* * Create labelvals so that we can verify our choices in the * second round of run-pre matching that considers data sections. */ ret = create_labelval(change, r->symbol, sym_addr, VAL); if (ret != OK) return ret; return add_dependency_on_address(change, sym_addr); } /* * Date relocations are created wherever __DATE__ or __TIME__ is used * in the kernel; we resolve them by simply copying in the date/time * obtained from run-pre matching the relevant compilation unit. */ static abort_t apply_howto_date(struct ksplice_mod_change *change, const struct ksplice_reloc *r) { if (r->symbol->candidate_vals != NULL) { ksdebug(change, "Failed to find %s for date\n", r->symbol->label); return FAILED_TO_FIND; } memcpy((unsigned char *)r->blank_addr, (const unsigned char *)r->symbol->value, r->howto->size); return OK; } /* * Given a relocation and its run address, compute the address of the * symbol the relocation referenced, and store it in *valp. */ static abort_t read_reloc_value(struct ksplice_mod_change *change, const struct ksplice_reloc *r, unsigned long addr, unsigned long *valp) { unsigned char bytes[sizeof(long)]; unsigned long val; const struct ksplice_reloc_howto *howto = r->howto; if (howto->size <= 0 || howto->size > sizeof(long)) { ksdebug(change, "Aborted. Invalid relocation size.\n"); return UNEXPECTED; } if (probe_kernel_read(bytes, (void *)addr, howto->size) == -EFAULT) return NO_MATCH; switch (howto->size) { case 1: val = *(uint8_t *)bytes; break; case 2: val = *(uint16_t *)bytes; break; case 4: val = *(uint32_t *)bytes; break; #if BITS_PER_LONG >= 64 case 8: val = *(uint64_t *)bytes; break; #endif /* BITS_PER_LONG */ default: ksdebug(change, "Aborted. Invalid relocation size.\n"); return UNEXPECTED; } val &= howto->dst_mask; if (howto->signed_addend) val |= -(val & (howto->dst_mask & ~(howto->dst_mask >> 1))); val <<= howto->rightshift; val -= r->insn_addend + r->target_addend; *valp = val; return OK; } /* * Given a relocation, the address of its storage unit, and the * address of the symbol the relocation references, write the * relocation's final value into the storage unit. */ static abort_t write_reloc_value(struct ksplice_mod_change *change, const struct ksplice_reloc *r, unsigned long addr, unsigned long sym_addr) { unsigned long val = sym_addr + r->target_addend + r->insn_addend; const struct ksplice_reloc_howto *howto = r->howto; val >>= howto->rightshift; switch (howto->size) { case 1: *(uint8_t *)addr = (*(uint8_t *)addr & ~howto->dst_mask) | (val & howto->dst_mask); break; case 2: *(uint16_t *)addr = (*(uint16_t *)addr & ~howto->dst_mask) | (val & howto->dst_mask); break; case 4: *(uint32_t *)addr = (*(uint32_t *)addr & ~howto->dst_mask) | (val & howto->dst_mask); break; #if BITS_PER_LONG >= 64 case 8: *(uint64_t *)addr = (*(uint64_t *)addr & ~howto->dst_mask) | (val & howto->dst_mask); break; #endif /* BITS_PER_LONG */ default: ksdebug(change, "Aborted. Invalid relocation size.\n"); return UNEXPECTED; } if (read_reloc_value(change, r, addr, &val) != OK || val != sym_addr) { ksdebug(change, "Aborted. Relocation overflow.\n"); return UNEXPECTED; } return OK; } static abort_t create_module_list_entry(struct ksplice_mod_change *change, bool to_be_applied) { struct ksplice_module_list_entry *entry = kmalloc(sizeof(*entry), GFP_KERNEL); if (entry == NULL) return OUT_OF_MEMORY; entry->new_code_mod_name = kstrdup(change->new_code_mod->name, GFP_KERNEL); if (entry->new_code_mod_name == NULL) { kfree(entry); return OUT_OF_MEMORY; } entry->target_mod_name = kstrdup(change->target_name, GFP_KERNEL); if (entry->target_mod_name == NULL) { kfree(entry->new_code_mod_name); kfree(entry); return OUT_OF_MEMORY; } /* The update's kid is guaranteed to outlast the module_list_entry */ entry->kid = change->update->kid; entry->applied = to_be_applied; list_add(&entry->update_list, &change->update->ksplice_module_list); return OK; } static void cleanup_module_list_entries(struct update *update) { struct ksplice_module_list_entry *entry; list_for_each_entry(entry, &update->ksplice_module_list, update_list) { kfree(entry->target_mod_name); kfree(entry->new_code_mod_name); } clear_list(&update->ksplice_module_list, struct ksplice_module_list_entry, update_list); } /* Replacement address used for functions deleted by the patch */ static void __attribute__((noreturn)) ksplice_deleted(void) { printk(KERN_CRIT "Called a kernel function deleted by Ksplice!\n"); BUG(); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) /* 91768d6c2bad0d2766a166f13f2f57e197de3458 was after 2.6.19 */ for (;;); #endif } /* Floodfill to run-pre match the sections within a change. */ static abort_t match_change_sections(struct ksplice_mod_change *change, bool consider_data_sections) { struct ksplice_section *sect; abort_t ret; int remaining = 0; bool progress; for (sect = change->old_code.sections; sect < change->old_code.sections_end; sect++) { if (((sect->flags & KSPLICE_SECTION_DATA) == 0 || (sect->flags & KSPLICE_SECTION_MATCH_DATA_EARLY) != 0) && (sect->flags & KSPLICE_SECTION_STRING) == 0 && (sect->flags & KSPLICE_SECTION_MATCHED) == 0) remaining++; } while (remaining > 0) { progress = false; for (sect = change->old_code.sections; sect < change->old_code.sections_end; sect++) { if ((sect->flags & KSPLICE_SECTION_MATCHED) != 0) continue; if ((!consider_data_sections && (sect->flags & KSPLICE_SECTION_DATA) != 0 && (sect->flags & KSPLICE_SECTION_MATCH_DATA_EARLY) == 0) || (sect->flags & KSPLICE_SECTION_STRING) != 0) continue; ret = find_section(change, sect); if (ret == OK) { sect->flags |= KSPLICE_SECTION_MATCHED; if ((sect->flags & KSPLICE_SECTION_DATA) == 0 || (sect->flags & KSPLICE_SECTION_MATCH_DATA_EARLY) != 0) remaining--; progress = true; } else if (ret != NO_MATCH) { return ret; } } if (progress) continue; for (sect = change->old_code.sections; sect < change->old_code.sections_end; sect++) { if ((sect->flags & KSPLICE_SECTION_MATCHED) != 0 || (sect->flags & KSPLICE_SECTION_STRING) != 0) continue; ksdebug(change, "run-pre: could not match %s " "section %s\n", (sect->flags & KSPLICE_SECTION_DATA) != 0 ? "data" : (sect->flags & KSPLICE_SECTION_RODATA) != 0 ? "rodata" : "text", sect->symbol->label); } ksdebug(change, "Aborted. run-pre: could not match some " "sections.\n"); return NO_MATCH; } return OK; } /* * Search for the section in the running kernel. Returns OK if and * only if it finds precisely one address in the kernel matching the * section. */ static abort_t find_section(struct ksplice_mod_change *change, struct ksplice_section *sect) { int i; abort_t ret; unsigned long run_addr; LIST_HEAD(vals); struct candidate_val *v, *n; #ifdef KSPLICE_STANDALONE ret = add_system_map_candidates(change, change->old_code.system_map, change->old_code.system_map_end, sect->symbol->label, &vals); if (ret != OK) { release_vals(&vals); return ret; } #endif /* KSPLICE_STANDALONE */ ret = lookup_symbol(change, sect->symbol, &vals); if (ret != OK) { release_vals(&vals); return ret; } ksdebug(change, "run-pre: starting sect search for %s\n", sect->symbol->label); list_for_each_entry_safe(v, n, &vals, list) { run_addr = v->val; yield(); ret = try_addr(change, sect, run_addr, NULL, RUN_PRE_INITIAL); if (ret == NO_MATCH) { list_del(&v->list); kfree(v); } else if (ret != OK) { release_vals(&vals); return ret; } } #if defined(KSPLICE_STANDALONE) && !defined(CONFIG_KALLSYMS) if (list_empty(&vals) && (sect->flags & KSPLICE_SECTION_DATA) == 0) { ret = brute_search_all(change, sect, &vals); if (ret != OK) { release_vals(&vals); return ret; } /* * Make sure run-pre matching output is displayed if * brute_search succeeds. */ if (singular(&vals)) { run_addr = list_entry(vals.next, struct candidate_val, list)->val; ret = try_addr(change, sect, run_addr, NULL, RUN_PRE_INITIAL); if (ret != OK) { ksdebug(change, "run-pre: Debug run failed for " "sect %s:\n", sect->symbol->label); release_vals(&vals); return ret; } } } #endif /* KSPLICE_STANDALONE && !CONFIG_KALLSYMS */ if (singular(&vals)) { LIST_HEAD(safety_records); run_addr = list_entry(vals.next, struct candidate_val, list)->val; ret = try_addr(change, sect, run_addr, &safety_records, RUN_PRE_FINAL); release_vals(&vals); if (ret != OK) { clear_list(&safety_records, struct safety_record, list); ksdebug(change, "run-pre: Final run failed for sect " "%s:\n", sect->symbol->label); } else { list_splice(&safety_records, &change->safety_records); } return ret; } else if (!list_empty(&vals)) { struct candidate_val *val; ksdebug(change, "run-pre: multiple candidates for sect %s:\n", sect->symbol->label); i = 0; list_for_each_entry(val, &vals, list) { i++; ksdebug(change, "%lx\n", val->val); if (i > 5) { ksdebug(change, "...\n"); break; } } release_vals(&vals); return NO_MATCH; } release_vals(&vals); return NO_MATCH; } /* * try_addr is the the interface to run-pre matching. Its primary * purpose is to manage debugging information for run-pre matching; * all the hard work is in run_pre_cmp. */ static abort_t try_addr(struct ksplice_mod_change *change, struct ksplice_section *sect, unsigned long run_addr, struct list_head *safety_records, enum run_pre_mode mode) { abort_t ret; const struct module *run_module = __module_address(run_addr); if (run_module == change->new_code_mod) { ksdebug(change, "run-pre: unexpected address %lx in new_code " "module %s for sect %s\n", run_addr, run_module->name, sect->symbol->label); return UNEXPECTED; } if (!patches_module(run_module, change->target)) { ksdebug(change, "run-pre: ignoring address %lx in other module " "%s for sect %s\n", run_addr, run_module == NULL ? "vmlinux" : run_module->name, sect->symbol->label); return NO_MATCH; } ret = create_labelval(change, sect->symbol, run_addr, TEMP); if (ret != OK) return ret; #ifdef CONFIG_FUNCTION_DATA_SECTIONS ret = run_pre_cmp(change, sect, run_addr, safety_records, mode); #else /* !CONFIG_FUNCTION_DATA_SECTIONS */ if ((sect->flags & KSPLICE_SECTION_TEXT) != 0) ret = arch_run_pre_cmp(change, sect, run_addr, safety_records, mode); else ret = run_pre_cmp(change, sect, run_addr, safety_records, mode); #endif /* CONFIG_FUNCTION_DATA_SECTIONS */ if (ret == NO_MATCH && mode != RUN_PRE_FINAL) { set_temp_labelvals(change, NOVAL); ksdebug(change, "run-pre: %s sect %s does not match (r_a=%lx " "p_a=%lx s=%lx)\n", (sect->flags & KSPLICE_SECTION_RODATA) != 0 ? "rodata" : (sect->flags & KSPLICE_SECTION_DATA) != 0 ? "data" : "text", sect->symbol->label, run_addr, sect->address, sect->size); ksdebug(change, "run-pre: "); if (change->update->debug >= 1) { #ifdef CONFIG_FUNCTION_DATA_SECTIONS ret = run_pre_cmp(change, sect, run_addr, safety_records, RUN_PRE_DEBUG); #else /* !CONFIG_FUNCTION_DATA_SECTIONS */ if ((sect->flags & KSPLICE_SECTION_TEXT) != 0) ret = arch_run_pre_cmp(change, sect, run_addr, safety_records, RUN_PRE_DEBUG); else ret = run_pre_cmp(change, sect, run_addr, safety_records, RUN_PRE_DEBUG); #endif /* CONFIG_FUNCTION_DATA_SECTIONS */ set_temp_labelvals(change, NOVAL); } ksdebug(change, "\n"); return ret; } else if (ret != OK) { set_temp_labelvals(change, NOVAL); return ret; } if (mode != RUN_PRE_FINAL) { set_temp_labelvals(change, NOVAL); ksdebug(change, "run-pre: candidate for sect %s=%lx\n", sect->symbol->label, run_addr); return OK; } set_temp_labelvals(change, VAL); ksdebug(change, "run-pre: found sect %s=%lx\n", sect->symbol->label, run_addr); return OK; } /* * run_pre_cmp is the primary run-pre matching function; it determines * whether the given ksplice_section matches the code or data in the * running kernel starting at run_addr. * * If run_pre_mode is RUN_PRE_FINAL, a safety record for the matched * section is created. * * The run_pre_mode is also used to determine what debugging * information to display. */ static abort_t run_pre_cmp(struct ksplice_mod_change *change, const struct ksplice_section *sect, unsigned long run_addr, struct list_head *safety_records, enum run_pre_mode mode) { int matched = 0; abort_t ret; const struct ksplice_reloc *r, *finger; const unsigned char *pre, *run, *pre_start, *run_start; unsigned char runval; pre_start = (const unsigned char *)sect->address; run_start = (const unsigned char *)run_addr; finger = init_reloc_search(change, sect); pre = pre_start; run = run_start; while (pre < pre_start + sect->size) { unsigned long offset = pre - pre_start; ret = lookup_reloc(change, &finger, (unsigned long)pre, &r); if (ret == OK) { ret = handle_reloc(change, sect, r, (unsigned long)run, mode); if (ret != OK) { if (mode == RUN_PRE_INITIAL) ksdebug(change, "reloc in sect does " "not match after %lx/%lx " "bytes\n", offset, sect->size); return ret; } if (mode == RUN_PRE_DEBUG) print_bytes(change, run, r->howto->size, pre, r->howto->size); pre += r->howto->size; run += r->howto->size; finger++; continue; } else if (ret != NO_MATCH) { return ret; } if ((sect->flags & KSPLICE_SECTION_TEXT) != 0) { ret = handle_paravirt(change, (unsigned long)pre, (unsigned long)run, &matched); if (ret != OK) return ret; if (matched != 0) { if (mode == RUN_PRE_DEBUG) print_bytes(change, run, matched, pre, matched); pre += matched; run += matched; continue; } } if (probe_kernel_read(&runval, (void *)run, 1) == -EFAULT) { if (mode == RUN_PRE_INITIAL) ksdebug(change, "sect unmapped after %lx/%lx " "bytes\n", offset, sect->size); return NO_MATCH; } if (runval != *pre && (sect->flags & KSPLICE_SECTION_DATA) == 0) { if (mode == RUN_PRE_INITIAL) ksdebug(change, "sect does not match after " "%lx/%lx bytes\n", offset, sect->size); if (mode == RUN_PRE_DEBUG) { print_bytes(change, run, 1, pre, 1); ksdebug(change, "[p_o=%lx] ! ", offset); print_bytes(change, run + 1, 2, pre + 1, 2); } return NO_MATCH; } if (mode == RUN_PRE_DEBUG) print_bytes(change, run, 1, pre, 1); pre++; run++; } return create_safety_record(change, sect, safety_records, run_addr, run - run_start); } static void print_bytes(struct ksplice_mod_change *change, const unsigned char *run, int runc, const unsigned char *pre, int prec) { int o; int matched = min(runc, prec); for (o = 0; o < matched; o++) { if (run[o] == pre[o]) ksdebug(change, "%02x ", run[o]); else ksdebug(change, "%02x/%02x ", run[o], pre[o]); } for (o = matched; o < runc; o++) ksdebug(change, "%02x/ ", run[o]); for (o = matched; o < prec; o++) ksdebug(change, "/%02x ", pre[o]); } #if defined(KSPLICE_STANDALONE) && !defined(CONFIG_KALLSYMS) static abort_t brute_search(struct ksplice_mod_change *change, struct ksplice_section *sect, const void *start, unsigned long len, struct list_head *vals) { unsigned long addr; char run, pre; abort_t ret; for (addr = (unsigned long)start; addr < (unsigned long)start + len; addr++) { if (addr % 100000 == 0) yield(); if (probe_kernel_read(&run, (void *)addr, 1) == -EFAULT) return OK; pre = *(const unsigned char *)(sect->address); if (run != pre) continue; ret = try_addr(change, sect, addr, NULL, RUN_PRE_INITIAL); if (ret == OK) { ret = add_candidate_val(change, vals, addr); if (ret != OK) return ret; } else if (ret != NO_MATCH) { return ret; } } return OK; } extern struct list_head modules; EXTRACT_SYMBOL(modules); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) /* 3abf024d2abb79614d8c4cb25a70d5596f77d0ad was after 2.6.24 */ EXTRACT_SYMBOL(init_mm); #endif /* LINUX_VERSION_CODE */ static abort_t brute_search_all(struct ksplice_mod_change *change, struct ksplice_section *sect, struct list_head *vals) { struct module *m; abort_t ret = OK; int saved_debug; ksdebug(change, "brute_search: searching for %s\n", sect->symbol->label); saved_debug = change->update->debug; change->update->debug = 0; list_for_each_entry(m, &modules, list) { if (!patches_module(m, change->target) || m == change->new_code_mod) continue; ret = brute_search(change, sect, m->module_core, m->core_size, vals); if (ret != OK) goto out; ret = brute_search(change, sect, m->module_init, m->init_size, vals); if (ret != OK) goto out; } ret = brute_search(change, sect, (const void *)init_mm.start_code, init_mm.end_code - init_mm.start_code, vals); out: change->update->debug = saved_debug; return ret; } #endif /* KSPLICE_STANDALONE && !CONFIG_KALLSYMS */ struct range { unsigned long address; unsigned long size; }; static int reloc_bsearch_compare(const void *key, const void *elt) { const struct range *range = key; const struct ksplice_reloc *r = elt; if (range->address + range->size <= r->blank_addr) return -1; if (range->address > r->blank_addr) return 1; return 0; } static const struct ksplice_reloc *find_reloc(const struct ksplice_reloc *start, const struct ksplice_reloc *end, unsigned long address, unsigned long size) { const struct ksplice_reloc *r; struct range range = { address, size }; r = bsearch((void *)&range, start, end - start, sizeof(*r), reloc_bsearch_compare); if (r == NULL) return NULL; while (r > start && (r - 1)->blank_addr >= address) r--; return r; } static const struct ksplice_reloc * init_reloc_search(struct ksplice_mod_change *change, const struct ksplice_section *sect) { const struct ksplice_reloc *r; r = find_reloc(change->old_code.relocs, change->old_code.relocs_end, sect->address, sect->size); if (r == NULL) return change->old_code.relocs_end; return r; } /* * lookup_reloc implements an amortized O(1) lookup for the next * old_code relocation. It must be called with a strictly increasing * sequence of addresses. * * The fingerp is private data for lookup_reloc, and needs to have * been initialized as a pointer to the result of find_reloc (or * init_reloc_search). */ static abort_t lookup_reloc(struct ksplice_mod_change *change, const struct ksplice_reloc **fingerp, unsigned long addr, const struct ksplice_reloc **relocp) { const struct ksplice_reloc *r = *fingerp; int canary_ret; while (r < change->old_code.relocs_end && addr >= r->blank_addr + r->howto->size && !(addr == r->blank_addr && r->howto->size == 0)) r++; *fingerp = r; if (r == change->old_code.relocs_end) return NO_MATCH; if (addr < r->blank_addr) return NO_MATCH; *relocp = r; if (r->howto->type != KSPLICE_HOWTO_RELOC) return OK; canary_ret = contains_canary(change, r->blank_addr, r->howto); if (canary_ret < 0) return UNEXPECTED; if (canary_ret == 0) { ksdebug(change, "run-pre: reloc skipped at p_a=%lx to %s+%lx " "(altinstr)\n", r->blank_addr, r->symbol->label, r->target_addend); return NO_MATCH; } if (addr != r->blank_addr) { ksdebug(change, "Invalid nonzero relocation offset\n"); return UNEXPECTED; } return OK; } static abort_t handle_howto_symbol(struct ksplice_mod_change *change, const struct ksplice_reloc *r, unsigned long run_addr, enum run_pre_mode mode) { if (mode == RUN_PRE_INITIAL) ksdebug(change, "run-pre: symbol %s at %lx\n", r->symbol->label, run_addr); return create_labelval(change, r->symbol, run_addr, TEMP); } static abort_t handle_reloc(struct ksplice_mod_change *change, const struct ksplice_section *sect, const struct ksplice_reloc *r, unsigned long run_addr, enum run_pre_mode mode) { switch (r->howto->type) { case KSPLICE_HOWTO_RELOC: return handle_howto_reloc(change, sect, r, run_addr, mode); case KSPLICE_HOWTO_DATE: case KSPLICE_HOWTO_TIME: return handle_howto_date(change, sect, r, run_addr, mode); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) #ifdef CONFIG_BUG case KSPLICE_HOWTO_BUG: return handle_bug(change, r, run_addr); #endif /* CONFIG_BUG */ #else /* LINUX_VERSION_CODE < */ /* 7664c5a1da4711bb6383117f51b94c8dc8f3f1cd was after 2.6.19 */ #endif /* LINUX_VERSION_CODE */ case KSPLICE_HOWTO_EXTABLE: return handle_extable(change, r, run_addr); case KSPLICE_HOWTO_SYMBOL: return handle_howto_symbol(change, r, run_addr, mode); default: ksdebug(change, "Unexpected howto type %d\n", r->howto->type); return UNEXPECTED; } } /* * For date/time relocations, we check that the sequence of bytes * matches the format of a date or time. */ static abort_t handle_howto_date(struct ksplice_mod_change *change, const struct ksplice_section *sect, const struct ksplice_reloc *r, unsigned long run_addr, enum run_pre_mode mode) { abort_t ret; char *buf = kmalloc(r->howto->size, GFP_KERNEL); if (buf == NULL) return OUT_OF_MEMORY; if (probe_kernel_read(buf, (void *)run_addr, r->howto->size) == -EFAULT) { ret = NO_MATCH; goto out; } switch (r->howto->type) { case KSPLICE_HOWTO_TIME: if (isdigit(buf[0]) && isdigit(buf[1]) && buf[2] == ':' && isdigit(buf[3]) && isdigit(buf[4]) && buf[5] == ':' && isdigit(buf[6]) && isdigit(buf[7])) ret = OK; else ret = NO_MATCH; break; case KSPLICE_HOWTO_DATE: if (isalpha(buf[0]) && isalpha(buf[1]) && isalpha(buf[2]) && buf[3] == ' ' && (buf[4] == ' ' || isdigit(buf[4])) && isdigit(buf[5]) && buf[6] == ' ' && isdigit(buf[7]) && isdigit(buf[8]) && isdigit(buf[9]) && isdigit(buf[10])) ret = OK; else ret = NO_MATCH; break; default: ret = UNEXPECTED; } if (ret == NO_MATCH && mode == RUN_PRE_INITIAL) ksdebug(change, "%s string: \"%.*s\" does not match format\n", r->howto->type == KSPLICE_HOWTO_DATE ? "date" : "time", r->howto->size, buf); if (ret != OK) goto out; ret = create_labelval(change, r->symbol, run_addr, TEMP); out: kfree(buf); return ret; } /* * Extract the value of a symbol used in a relocation in the pre code * during run-pre matching, giving an error if it conflicts with a * previously found value of that symbol */ static abort_t handle_howto_reloc(struct ksplice_mod_change *change, const struct ksplice_section *sect, const struct ksplice_reloc *r, unsigned long run_addr, enum run_pre_mode mode) { struct ksplice_section *sym_sect = symbol_section(change, r->symbol); unsigned long offset = r->target_addend; unsigned long val; abort_t ret; ret = read_reloc_value(change, r, run_addr, &val); if (ret != OK) return ret; if (r->howto->pcrel) val += run_addr; #ifndef CONFIG_FUNCTION_DATA_SECTIONS if (sym_sect == NULL || sym_sect->match_map == NULL || offset == 0) { ; } else if (offset < 0 || offset >= sym_sect->size) { ksdebug(change, "Out of range relocation: %s+%lx -> %s+%lx", sect->symbol->label, r->blank_addr - sect->address, r->symbol->label, offset); return NO_MATCH; } else if (sect == sym_sect && sect->match_map[offset] == NULL) { sym_sect->match_map[offset] = (const unsigned char *)r->symbol->value + offset; sym_sect->unmatched++; } else if (sect == sym_sect && (unsigned long)sect->match_map[offset] == r->symbol->value + offset) { ; } else if (sect == sym_sect) { ksdebug(change, "Relocations to nonmatching locations within " "section %s: %lx does not match %lx\n", sect->symbol->label, offset, (unsigned long)sect->match_map[offset] - r->symbol->value); return NO_MATCH; } else if ((sym_sect->flags & KSPLICE_SECTION_MATCHED) == 0) { if (mode == RUN_PRE_INITIAL) ksdebug(change, "Delaying matching of %s due to reloc " "from to unmatching section: %s+%lx\n", sect->symbol->label, r->symbol->label, offset); return NO_MATCH; } else if (sym_sect->match_map[offset] == NULL) { if (mode == RUN_PRE_INITIAL) ksdebug(change, "Relocation not to instruction " "boundary: %s+%lx -> %s+%lx", sect->symbol->label, r->blank_addr - sect->address, r->symbol->label, offset); return NO_MATCH; } else if ((unsigned long)sym_sect->match_map[offset] != r->symbol->value + offset) { if (mode == RUN_PRE_INITIAL) ksdebug(change, "Match map shift %s+%lx: %lx != %lx\n", r->symbol->label, offset, r->symbol->value + offset, (unsigned long)sym_sect->match_map[offset]); val += r->symbol->value + offset - (unsigned long)sym_sect->match_map[offset]; } #endif /* !CONFIG_FUNCTION_DATA_SECTIONS */ if (mode == RUN_PRE_INITIAL) ksdebug(change, "run-pre: reloc at r_a=%lx p_a=%lx to %s+%lx: " "found %s = %lx\n", run_addr, r->blank_addr, r->symbol->label, offset, r->symbol->label, val); if (contains_canary(change, run_addr, r->howto) != 0) { ksdebug(change, "Aborted. Unexpected canary in run code at %lx" "\n", run_addr); return UNEXPECTED; } if ((sect->flags & KSPLICE_SECTION_DATA) != 0 && sect->symbol == r->symbol) return OK; ret = create_labelval(change, r->symbol, val, TEMP); if (ret == NO_MATCH && mode == RUN_PRE_INITIAL) ksdebug(change, "run-pre: reloc at r_a=%lx p_a=%lx: labelval " "%s = %lx does not match expected %lx\n", run_addr, r->blank_addr, r->symbol->label, r->symbol->value, val); if (ret != OK) return ret; if (sym_sect != NULL && (sym_sect->flags & KSPLICE_SECTION_MATCHED) == 0 && (sym_sect->flags & KSPLICE_SECTION_STRING) != 0) { if (mode == RUN_PRE_INITIAL) ksdebug(change, "Recursively comparing string section " "%s\n", sym_sect->symbol->label); else if (mode == RUN_PRE_DEBUG) ksdebug(change, "[str start] "); ret = run_pre_cmp(change, sym_sect, val, NULL, mode); if (mode == RUN_PRE_DEBUG) ksdebug(change, "[str end] "); if (ret == OK && mode == RUN_PRE_INITIAL) ksdebug(change, "Successfully matched string section %s" "\n", sym_sect->symbol->label); else if (mode == RUN_PRE_INITIAL) ksdebug(change, "Failed to match string section %s\n", sym_sect->symbol->label); } return ret; } #ifdef CONFIG_GENERIC_BUG #ifdef KSPLICE_NO_KERNEL_SUPPORT EXTRACT_SYMBOL(find_bug); #endif /* KSPLICE_NO_KERNEL_SUPPORT */ static abort_t handle_bug(struct ksplice_mod_change *change, const struct ksplice_reloc *r, unsigned long run_addr) { const struct bug_entry *run_bug = find_bug(run_addr); struct ksplice_section *bug_sect = symbol_section(change, r->symbol); if (run_bug == NULL) return NO_MATCH; if (bug_sect == NULL) return UNEXPECTED; return create_labelval(change, bug_sect->symbol, (unsigned long)run_bug, TEMP); } #endif /* CONFIG_GENERIC_BUG */ #ifdef KSPLICE_NO_KERNEL_SUPPORT EXTRACT_SYMBOL(search_exception_tables); #endif /* KSPLICE_NO_KERNEL_SUPPORT */ static abort_t handle_extable(struct ksplice_mod_change *change, const struct ksplice_reloc *r, unsigned long run_addr) { const struct exception_table_entry *run_ent = search_exception_tables(run_addr); struct ksplice_section *ex_sect = symbol_section(change, r->symbol); if (run_ent == NULL) return NO_MATCH; if (ex_sect == NULL) return UNEXPECTED; return create_labelval(change, ex_sect->symbol, (unsigned long)run_ent, TEMP); } static int symbol_section_bsearch_compare(const void *a, const void *b) { const struct ksplice_symbol *sym = a; const struct ksplice_section *sect = b; return strcmp(sym->label, sect->symbol->label); } static int compare_section_labels(const void *va, const void *vb) { const struct ksplice_section *a = va, *b = vb; return strcmp(a->symbol->label, b->symbol->label); } static struct ksplice_section *symbol_section(struct ksplice_mod_change *change, const struct ksplice_symbol *sym) { return bsearch(sym, change->old_code.sections, change->old_code.sections_end - change->old_code.sections, sizeof(struct ksplice_section), symbol_section_bsearch_compare); } /* Find the relocation for the oldaddr of a ksplice_patch */ static const struct ksplice_reloc * patch_reloc(struct ksplice_mod_change *change, const struct ksplice_patch *p) { unsigned long addr = (unsigned long)&p->oldaddr; const struct ksplice_reloc *r = find_reloc(change->new_code.relocs, change->new_code.relocs_end, addr, sizeof(addr)); if (r == NULL || r->blank_addr < addr || r->blank_addr >= addr + sizeof(addr)) return NULL; return r; } /* * Populates vals with the possible values for ksym from the various * sources Ksplice uses to resolve symbols */ static abort_t lookup_symbol(struct ksplice_mod_change *change, const struct ksplice_symbol *ksym, struct list_head *vals) { abort_t ret; #ifdef KSPLICE_STANDALONE if (!bootstrapped) return OK; #endif /* KSPLICE_STANDALONE */ if (ksym->candidate_vals == NULL) { release_vals(vals); ksdebug(change, "using detected sym %s=%lx\n", ksym->label, ksym->value); return add_candidate_val(change, vals, ksym->value); } #ifdef CONFIG_MODULE_UNLOAD if (strcmp(ksym->label, "cleanup_module") == 0 && change->target != NULL && change->target->exit != NULL) { ret = add_candidate_val(change, vals, (unsigned long)change->target->exit); if (ret != OK) return ret; } #endif if (ksym->name != NULL) { struct candidate_val *val; list_for_each_entry(val, ksym->candidate_vals, list) { ret = add_candidate_val(change, vals, val->val); if (ret != OK) return ret; } ret = new_export_lookup(change, ksym->name, vals); if (ret != OK) return ret; } return OK; } #ifdef KSPLICE_STANDALONE static abort_t add_system_map_candidates(struct ksplice_mod_change *change, const struct ksplice_system_map *start, const struct ksplice_system_map *end, const char *label, struct list_head *vals) { abort_t ret; long off; int i; const struct ksplice_system_map *smap; /* Some Fedora kernel releases have System.map files whose symbol * addresses disagree with the running kernel by a constant address * offset because of the CONFIG_PHYSICAL_START and CONFIG_PHYSICAL_ALIGN * values used to compile these kernels. This constant address offset * is always a multiple of 0x100000. * * If we observe an offset that is NOT a multiple of 0x100000, then the * user provided us with an incorrect System.map file, and we should * abort. * If we observe an offset that is a multiple of 0x100000, then we can * adjust the System.map address values accordingly and proceed. */ off = (unsigned long)printk - change->map_printk; if (off & 0xfffff) { ksdebug(change, "Aborted. System.map does not match kernel.\n"); return BAD_SYSTEM_MAP; } smap = bsearch(label, start, end - start, sizeof(*smap), system_map_bsearch_compare); if (smap == NULL) return OK; for (i = 0; i < smap->nr_candidates; i++) { ret = add_candidate_val(change, vals, smap->candidates[i] + off); if (ret != OK) return ret; } return OK; } static int system_map_bsearch_compare(const void *key, const void *elt) { const struct ksplice_system_map *map = elt; const char *label = key; return strcmp(label, map->label); } #endif /* !KSPLICE_STANDALONE */ /* * An update could one module to export a symbol and at the same time * change another module to use that symbol. This violates the normal * situation where the changes can be handled independently. * * new_export_lookup obtains symbol values from the changes to the * exported symbol table made by other changes. */ static abort_t new_export_lookup(struct ksplice_mod_change *ichange, const char *name, struct list_head *vals) { struct ksplice_mod_change *change; struct ksplice_patch *p; list_for_each_entry(change, &ichange->update->changes, list) { for (p = change->patches; p < change->patches_end; p++) { const struct kernel_symbol *sym; const struct ksplice_reloc *r; if (p->type != KSPLICE_PATCH_EXPORT || strcmp(name, *(const char **)p->contents) != 0) continue; /* Check that the p->oldaddr reloc has been resolved. */ r = patch_reloc(change, p); if (r == NULL || contains_canary(change, r->blank_addr, r->howto) != 0) continue; sym = (const struct kernel_symbol *)r->symbol->value; /* * Check that the sym->value reloc has been resolved, * if there is a Ksplice relocation there. */ r = find_reloc(change->new_code.relocs, change->new_code.relocs_end, (unsigned long)&sym->value, sizeof(&sym->value)); if (r != NULL && r->blank_addr == (unsigned long)&sym->value && contains_canary(change, r->blank_addr, r->howto) != 0) continue; return add_candidate_val(ichange, vals, sym->value); } } return OK; } #ifdef KSPLICE_STANDALONE EXTRACT_SYMBOL(bust_spinlocks); #endif /* KSPLICE_STANDALONE */ /* * When patch_action is called, the update should be fully prepared. * patch_action will try to actually insert or remove trampolines for * the update. */ static abort_t patch_action(struct update *update, enum ksplice_action action) { static int (*const __patch_actions[KS_ACTIONS])(void *) = { [KS_APPLY] = __apply_patches, [KS_REVERSE] = __reverse_patches, }; int i; abort_t ret; struct ksplice_mod_change *change; ret = map_trampoline_pages(update); if (ret != OK) return ret; list_for_each_entry(change, &update->changes, list) { const typeof(int (*)(void)) *f; for (f = change->hooks[action].pre; f < change->hooks[action].pre_end; f++) { if ((*f)() != 0) { ret = CALL_FAILED; goto out; } } } for (i = 0; i < 5; i++) { cleanup_conflicts(update); #ifdef KSPLICE_STANDALONE bust_spinlocks(1); #endif /* KSPLICE_STANDALONE */ ret = (__force abort_t)stop_machine(__patch_actions[action], update, NULL); #ifdef KSPLICE_STANDALONE bust_spinlocks(0); #endif /* KSPLICE_STANDALONE */ if (ret != CODE_BUSY) break; set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(msecs_to_jiffies(1000)); } out: unmap_trampoline_pages(update); if (ret == CODE_BUSY) { print_conflicts(update); _ksdebug(update, "Aborted %s. stack check: to-be-%s " "code is busy.\n", update->kid, action == KS_APPLY ? "replaced" : "reversed"); } else if (ret == ALREADY_REVERSED) { _ksdebug(update, "Aborted %s. Ksplice update %s is already " "reversed.\n", update->kid, update->kid); } else if (ret == MODULE_BUSY) { _ksdebug(update, "Update %s is in use by another module\n", update->kid); } if (ret != OK) { list_for_each_entry(change, &update->changes, list) { const typeof(void (*)(void)) *f; for (f = change->hooks[action].fail; f < change->hooks[action].fail_end; f++) (*f)(); } return ret; } list_for_each_entry(change, &update->changes, list) { const typeof(void (*)(void)) *f; for (f = change->hooks[action].post; f < change->hooks[action].post_end; f++) (*f)(); } _ksdebug(update, "Atomic patch %s for %s complete\n", action == KS_APPLY ? "insertion" : "removal", update->kid); return OK; } /* Atomically insert the update; run from within stop_machine */ static int __apply_patches(void *updateptr) { struct update *update = updateptr; struct ksplice_mod_change *change; struct ksplice_module_list_entry *entry; struct ksplice_patch *p; abort_t ret; if (update->stage == STAGE_APPLIED) return (__force int)OK; if (update->stage != STAGE_PREPARING) return (__force int)UNEXPECTED; ret = check_each_task(update); if (ret != OK) return (__force int)ret; list_for_each_entry(change, &update->changes, list) { if (try_module_get(change->new_code_mod) != 1) { struct ksplice_mod_change *change1; list_for_each_entry(change1, &update->changes, list) { if (change1 == change) break; module_put(change1->new_code_mod); } module_put(THIS_MODULE); return (__force int)UNEXPECTED; } } list_for_each_entry(change, &update->changes, list) { const typeof(int (*)(void)) *f; for (f = change->hooks[KS_APPLY].check; f < change->hooks[KS_APPLY].check_end; f++) { if ((*f)() != 0) return (__force int)CALL_FAILED; } } /* Commit point: the update application will succeed. */ update->stage = STAGE_APPLIED; #ifdef TAINT_KSPLICE add_taint(TAINT_KSPLICE); #endif list_for_each_entry(entry, &update->ksplice_module_list, update_list) list_add(&entry->list, &ksplice_modules); list_for_each_entry(change, &update->changes, list) { for (p = change->patches; p < change->patches_end; p++) insert_trampoline(p); } list_for_each_entry(change, &update->changes, list) { const typeof(void (*)(void)) *f; for (f = change->hooks[KS_APPLY].intra; f < change->hooks[KS_APPLY].intra_end; f++) (*f)(); } return (__force int)OK; } /* Atomically remove the update; run from within stop_machine */ static int __reverse_patches(void *updateptr) { struct update *update = updateptr; struct ksplice_mod_change *change; struct ksplice_module_list_entry *entry; const struct ksplice_patch *p; abort_t ret; if (update->stage != STAGE_APPLIED) return (__force int)OK; #ifdef CONFIG_MODULE_UNLOAD list_for_each_entry(change, &update->changes, list) { if (module_refcount(change->new_code_mod) != 1) return (__force int)MODULE_BUSY; } #endif /* CONFIG_MODULE_UNLOAD */ list_for_each_entry(entry, &update->ksplice_module_list, update_list) { if (!entry->applied && find_module(entry->target_mod_name) != NULL) return COLD_UPDATE_LOADED; } ret = check_each_task(update); if (ret != OK) return (__force int)ret; list_for_each_entry(change, &update->changes, list) { for (p = change->patches; p < change->patches_end; p++) { ret = verify_trampoline(change, p); if (ret != OK) return (__force int)ret; } } list_for_each_entry(change, &update->changes, list) { const typeof(int (*)(void)) *f; for (f = change->hooks[KS_REVERSE].check; f < change->hooks[KS_REVERSE].check_end; f++) { if ((*f)() != 0) return (__force int)CALL_FAILED; } } /* Commit point: the update reversal will succeed. */ update->stage = STAGE_REVERSED; list_for_each_entry(change, &update->changes, list) module_put(change->new_code_mod); list_for_each_entry(entry, &update->ksplice_module_list, update_list) list_del(&entry->list); list_for_each_entry(change, &update->changes, list) { const typeof(void (*)(void)) *f; for (f = change->hooks[KS_REVERSE].intra; f < change->hooks[KS_REVERSE].intra_end; f++) (*f)(); } list_for_each_entry(change, &update->changes, list) { for (p = change->patches; p < change->patches_end; p++) remove_trampoline(p); } return (__force int)OK; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) /* 5d4564e68210e4b1edb3f013bc3e59982bb35737 was after 2.6.10 */ EXTRACT_SYMBOL(tasklist_lock); #endif /* LINUX_VERSION_CODE */ /* * Check whether any thread's instruction pointer or any address of * its stack is contained in one of the safety_records associated with * the update. * * check_each_task must be called from inside stop_machine, because it * does not take tasklist_lock (which cannot be held by anyone else * during stop_machine). */ static abort_t check_each_task(struct update *update) { const struct task_struct *g, *p; abort_t status = OK, ret; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) /* 5d4564e68210e4b1edb3f013bc3e59982bb35737 was after 2.6.10 */ read_lock(&tasklist_lock); #endif /* LINUX_VERSION_CODE */ do_each_thread(g, p) { /* do_each_thread is a double loop! */ ret = check_task(update, p, false); if (ret != OK) { check_task(update, p, true); status = ret; } if (ret != OK && ret != CODE_BUSY) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) /* 5d4564e68210e4b1edb3f013bc3e59982bb35737 was after 2.6.10 */ goto out; #else /* LINUX_VERSION_CODE < */ return ret; #endif /* LINUX_VERSION_CODE */ } while_each_thread(g, p); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) /* 5d4564e68210e4b1edb3f013bc3e59982bb35737 was after 2.6.10 */ out: read_unlock(&tasklist_lock); #endif /* LINUX_VERSION_CODE */ return status; } #ifdef KSPLICE_NO_KERNEL_SUPPORT EXTRACT_SYMBOL(task_curr); #endif /* KSPLICE_NO_KERNEL_SUPPORT */ static abort_t check_task(struct update *update, const struct task_struct *t, bool rerun) { abort_t status, ret; struct conflict *conf = NULL; if (rerun) { conf = kmalloc(sizeof(*conf), GFP_ATOMIC); if (conf == NULL) return OUT_OF_MEMORY; conf->process_name = kstrdup(t->comm, GFP_ATOMIC); if (conf->process_name == NULL) { kfree(conf); return OUT_OF_MEMORY; } conf->pid = t->pid; INIT_LIST_HEAD(&conf->stack); list_add(&conf->list, &update->conflicts); } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) if (t->state == TASK_DEAD) #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) /* c394cc9fbb367f87faa2228ec2eabacd2d4701c6 was after 2.6.18 */ if ((t->flags & PF_DEAD) != 0) #endif return OK; status = check_address(update, conf, KSPLICE_IP(t)); ret = check_address(update, conf, (unsigned long)task_thread_info(t)-> restart_block.fn); if (status == OK) status = ret; if (t == current) { ret = check_stack(update, conf, task_thread_info(t), (unsigned long *)__builtin_frame_address(0)); if (status == OK) status = ret; } else if (!task_curr(t)) { ret = check_stack(update, conf, task_thread_info(t), (unsigned long *)KSPLICE_SP(t)); if (status == OK) status = ret; } else if (!is_stop_machine(t)) { status = UNEXPECTED_RUNNING_TASK; } return status; } static abort_t check_stack(struct update *update, struct conflict *conf, const struct thread_info *tinfo, const unsigned long *stack) { abort_t status = OK, ret; unsigned long addr; while (valid_stack_ptr(tinfo, stack)) { addr = *stack++; ret = check_address(update, conf, addr); if (ret != OK) status = ret; } return status; } static abort_t check_address(struct update *update, struct conflict *conf, unsigned long addr) { abort_t status = OK, ret; const struct safety_record *rec; struct ksplice_mod_change *change; struct conflict_addr *ca = NULL; if (conf != NULL) { ca = kmalloc(sizeof(*ca), GFP_ATOMIC); if (ca == NULL) return OUT_OF_MEMORY; ca->addr = addr; ca->has_conflict = false; ca->label = NULL; list_add(&ca->list, &conf->stack); } list_for_each_entry(change, &update->changes, list) { unsigned long tramp_addr = follow_trampolines(change, addr); list_for_each_entry(rec, &change->safety_records, list) { ret = check_record(ca, rec, tramp_addr); if (ret != OK) status = ret; } } return status; } static abort_t check_record(struct conflict_addr *ca, const struct safety_record *rec, unsigned long addr) { if (addr >= rec->addr && addr < rec->addr + rec->size) { if (ca != NULL) { ca->label = rec->label; ca->has_conflict = true; } return CODE_BUSY; } return OK; } /* Is the task one of the stop_machine tasks? */ static bool is_stop_machine(const struct task_struct *t) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) const char *kstop_prefix = "kstop/"; #else /* LINUX_VERSION_CODE < */ /* c9583e55fa2b08a230c549bd1e3c0bde6c50d9cc was after 2.6.27 */ const char *kstop_prefix = "kstop"; #endif /* LINUX_VERSION_CODE */ const char *num; if (!strstarts(t->comm, kstop_prefix)) return false; num = t->comm + strlen(kstop_prefix); return num[strspn(num, "0123456789")] == '\0'; #else /* LINUX_VERSION_CODE < */ /* ffdb5976c47609c862917d4c186ecbb5706d2dda was after 2.6.26 */ return strcmp(t->comm, "kstopmachine") == 0; #endif /* LINUX_VERSION_CODE */ } static void cleanup_conflicts(struct update *update) { struct conflict *conf; list_for_each_entry(conf, &update->conflicts, list) { clear_list(&conf->stack, struct conflict_addr, list); kfree(conf->process_name); } clear_list(&update->conflicts, struct conflict, list); } static void print_conflicts(struct update *update) { const struct conflict *conf; const struct conflict_addr *ca; list_for_each_entry(conf, &update->conflicts, list) { _ksdebug(update, "stack check: pid %d (%s):", conf->pid, conf->process_name); list_for_each_entry(ca, &conf->stack, list) { _ksdebug(update, " %lx", ca->addr); if (ca->has_conflict) _ksdebug(update, " [<-CONFLICT]"); } _ksdebug(update, "\n"); } } static void insert_trampoline(struct ksplice_patch *p) { mm_segment_t old_fs = get_fs(); set_fs(KERNEL_DS); memcpy(p->saved, p->vaddr, p->size); memcpy(p->vaddr, p->contents, p->size); flush_icache_range(p->oldaddr, p->oldaddr + p->size); set_fs(old_fs); } static abort_t verify_trampoline(struct ksplice_mod_change *change, const struct ksplice_patch *p) { if (memcmp(p->vaddr, p->contents, p->size) != 0) { ksdebug(change, "Aborted. Trampoline at %lx has been " "overwritten.\n", p->oldaddr); return CODE_BUSY; } return OK; } static void remove_trampoline(const struct ksplice_patch *p) { mm_segment_t old_fs = get_fs(); set_fs(KERNEL_DS); memcpy(p->vaddr, p->saved, p->size); flush_icache_range(p->oldaddr, p->oldaddr + p->size); set_fs(old_fs); } /* Returns NO_MATCH if there's already a labelval with a different value */ static abort_t create_labelval(struct ksplice_mod_change *change, struct ksplice_symbol *ksym, unsigned long val, int status) { val = follow_trampolines(change, val); if (ksym->candidate_vals == NULL) return ksym->value == val ? OK : NO_MATCH; ksym->value = val; if (status == TEMP) { struct labelval *lv = kmalloc(sizeof(*lv), GFP_KERNEL); if (lv == NULL) return OUT_OF_MEMORY; lv->symbol = ksym; lv->saved_vals = ksym->candidate_vals; list_add(&lv->list, &change->temp_labelvals); } ksym->candidate_vals = NULL; return OK; } /* * Creates a new safety_record for a old_code section based on its * ksplice_section and run-pre matching information. */ static abort_t create_safety_record(struct ksplice_mod_change *change, const struct ksplice_section *sect, struct list_head *record_list, unsigned long run_addr, unsigned long run_size) { struct safety_record *rec; struct ksplice_patch *p; if (record_list == NULL) return OK; for (p = change->patches; p < change->patches_end; p++) { const struct ksplice_reloc *r = patch_reloc(change, p); if (strcmp(sect->symbol->label, r->symbol->label) == 0) break; } if (p >= change->patches_end) return OK; rec = kmalloc(sizeof(*rec), GFP_KERNEL); if (rec == NULL) return OUT_OF_MEMORY; /* * The old_code might be unloaded when checking reversing * patches, so we need to kstrdup the label here. */ rec->label = kstrdup(sect->symbol->label, GFP_KERNEL); if (rec->label == NULL) { kfree(rec); return OUT_OF_MEMORY; } rec->addr = run_addr; rec->size = run_size; list_add(&rec->list, record_list); return OK; } static abort_t add_candidate_val(struct ksplice_mod_change *change, struct list_head *vals, unsigned long val) { struct candidate_val *tmp, *new; /* * Careful: follow trampolines before comparing values so that we do * not mistake the obsolete function for another copy of the function. */ val = follow_trampolines(change, val); list_for_each_entry(tmp, vals, list) { if (tmp->val == val) return OK; } new = kmalloc(sizeof(*new), GFP_KERNEL); if (new == NULL) return OUT_OF_MEMORY; new->val = val; list_add(&new->list, vals); return OK; } static void release_vals(struct list_head *vals) { clear_list(vals, struct candidate_val, list); } /* * The temp_labelvals list is used to cache those temporary labelvals * that have been created to cross-check the symbol values obtained * from different relocations within a single section being matched. * * If status is VAL, commit the temp_labelvals as final values. * * If status is NOVAL, restore the list of possible values to the * ksplice_symbol, so that it no longer has a known value. */ static void set_temp_labelvals(struct ksplice_mod_change *change, int status) { struct labelval *lv, *n; list_for_each_entry_safe(lv, n, &change->temp_labelvals, list) { if (status == NOVAL) { lv->symbol->candidate_vals = lv->saved_vals; } else { release_vals(lv->saved_vals); kfree(lv->saved_vals); } list_del(&lv->list); kfree(lv); } } /* Is there a Ksplice canary with given howto at blank_addr? */ static int contains_canary(struct ksplice_mod_change *change, unsigned long blank_addr, const struct ksplice_reloc_howto *howto) { switch (howto->size) { case 1: return (*(uint8_t *)blank_addr & howto->dst_mask) == (KSPLICE_CANARY & howto->dst_mask); case 2: return (*(uint16_t *)blank_addr & howto->dst_mask) == (KSPLICE_CANARY & howto->dst_mask); case 4: return (*(uint32_t *)blank_addr & howto->dst_mask) == (KSPLICE_CANARY & howto->dst_mask); #if BITS_PER_LONG >= 64 case 8: return (*(uint64_t *)blank_addr & howto->dst_mask) == (KSPLICE_CANARY & howto->dst_mask); #endif /* BITS_PER_LONG */ default: ksdebug(change, "Aborted. Invalid relocation size.\n"); return -1; } } #ifdef KSPLICE_NO_KERNEL_SUPPORT EXTRACT_SYMBOL(__kernel_text_address); #endif /* KSPLICE_NO_KERNEL_SUPPORT */ /* * Compute the address of the code you would actually run if you were * to call the function at addr (i.e., follow the sequence of jumps * starting at addr) */ static unsigned long follow_trampolines(struct ksplice_mod_change *change, unsigned long addr) { unsigned long new_addr; struct module *m; while (1) { #ifdef KSPLICE_STANDALONE if (!bootstrapped) return addr; #endif /* KSPLICE_STANDALONE */ if (!__kernel_text_address(addr) || trampoline_target(change, addr, &new_addr) != OK) return addr; m = __module_text_address(new_addr); if (m == NULL || m == change->target || !strstarts(m->name, "ksplice")) return addr; addr = new_addr; } } /* Does module a patch module b? */ static bool patches_module(const struct module *a, const struct module *b) { #ifdef KSPLICE_NO_KERNEL_SUPPORT const char *name; const char *modname = b == NULL ? "vmlinux" : b->name; if (a == b) return true; if (a == NULL || !strstarts(a->name, "ksplice_")) return false; name = a->name + strlen("ksplice_"); name += strcspn(name, "_"); if (name[0] != '_') return false; name++; return strstarts(name, modname) && #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) strcmp(name + strlen(modname), "_new") == 0; #else /* LINUX_VERSION_CODE < */ /* 0e8a2de644a93132594f66222a9d48405674eacd was after 2.6.9 */ (strcmp(name + strlen(modname), "_n") == 0 || strcmp(name + strlen(modname), "_new") == 0); #endif /* LINUX_VERSION_CODE */ #else /* !KSPLICE_NO_KERNEL_SUPPORT */ struct ksplice_module_list_entry *entry; if (a == b) return true; list_for_each_entry(entry, &ksplice_modules, list) { if (strcmp(entry->target_mod_name, b->name) == 0 && strcmp(entry->new_code_mod_name, a->name) == 0) return true; } return false; #endif /* KSPLICE_NO_KERNEL_SUPPORT */ } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) /* 66f92cf9d415e96a5bdd6c64de8dd8418595d2fc was after 2.6.29 */ static bool strstarts(const char *str, const char *prefix) { return strncmp(str, prefix, strlen(prefix)) == 0; } #endif /* LINUX_VERSION_CODE */ static bool singular(struct list_head *list) { return !list_empty(list) && list->next->next == list; } static void *bsearch(const void *key, const void *base, size_t n, size_t size, int (*cmp)(const void *key, const void *elt)) { int start = 0, end = n - 1, mid, result; if (n == 0) return NULL; while (start <= end) { mid = (start + end) / 2; result = cmp(key, base + mid * size); if (result < 0) end = mid - 1; else if (result > 0) start = mid + 1; else return (void *)base + mid * size; } return NULL; } static int compare_relocs(const void *a, const void *b) { const struct ksplice_reloc *ra = a, *rb = b; if (ra->blank_addr > rb->blank_addr) return 1; else if (ra->blank_addr < rb->blank_addr) return -1; else return ra->howto->size - rb->howto->size; } #ifdef KSPLICE_STANDALONE static int compare_system_map(const void *a, const void *b) { const struct ksplice_system_map *sa = a, *sb = b; return strcmp(sa->label, sb->label); } #endif /* KSPLICE_STANDALONE */ #ifdef CONFIG_DEBUG_FS #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) /* Old kernels don't have debugfs_create_blob */ static ssize_t read_file_blob(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct debugfs_blob_wrapper *blob = file->private_data; return simple_read_from_buffer(user_buf, count, ppos, blob->data, blob->size); } static int blob_open(struct inode *inode, struct file *file) { if (inode->i_private) file->private_data = inode->i_private; return 0; } static struct file_operations fops_blob = { .read = read_file_blob, .open = blob_open, }; static struct dentry *debugfs_create_blob(const char *name, mode_t mode, struct dentry *parent, struct debugfs_blob_wrapper *blob) { return debugfs_create_file(name, mode, parent, blob, &fops_blob); } #endif /* LINUX_VERSION_CODE */ static abort_t init_debug_buf(struct update *update) { update->debug_blob.size = 0; update->debug_blob.data = NULL; update->debugfs_dentry = debugfs_create_blob(update->name, S_IFREG | S_IRUSR, NULL, &update->debug_blob); if (update->debugfs_dentry == NULL) return OUT_OF_MEMORY; return OK; } static void clear_debug_buf(struct update *update) { if (update->debugfs_dentry == NULL) return; debugfs_remove(update->debugfs_dentry); update->debugfs_dentry = NULL; update->debug_blob.size = 0; vfree(update->debug_blob.data); update->debug_blob.data = NULL; } static int _ksdebug(struct update *update, const char *fmt, ...) { va_list args; unsigned long size, old_size, new_size; if (update->debug == 0) return 0; /* size includes the trailing '\0' */ va_start(args, fmt); size = 1 + vsnprintf(update->debug_blob.data, 0, fmt, args); va_end(args); old_size = update->debug_blob.size == 0 ? 0 : max(PAGE_SIZE, roundup_pow_of_two(update->debug_blob.size)); new_size = update->debug_blob.size + size == 0 ? 0 : max(PAGE_SIZE, roundup_pow_of_two(update->debug_blob.size + size)); if (new_size > old_size) { char *buf = vmalloc(new_size); if (buf == NULL) return -ENOMEM; memcpy(buf, update->debug_blob.data, update->debug_blob.size); vfree(update->debug_blob.data); update->debug_blob.data = buf; } va_start(args, fmt); update->debug_blob.size += vsnprintf(update->debug_blob.data + update->debug_blob.size, size, fmt, args); va_end(args); return 0; } #else /* CONFIG_DEBUG_FS */ static abort_t init_debug_buf(struct update *update) { return OK; } static void clear_debug_buf(struct update *update) { return; } static int _ksdebug(struct update *update, const char *fmt, ...) { va_list args; if (update->debug == 0) return 0; if (!update->debug_continue_line) printk(KERN_DEBUG "ksplice: "); va_start(args, fmt); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9) vprintk(fmt, args); #else /* LINUX_VERSION_CODE < */ /* 683b229286b429244f35726b3c18caec429233bd was after 2.6.8 */ { char *buf = kvasprintf(GFP_KERNEL, fmt, args); printk("%s", buf); kfree(buf); } #endif /* LINUX_VERSION_CODE */ va_end(args); update->debug_continue_line = fmt[0] == '\0' || fmt[strlen(fmt) - 1] != '\n'; return 0; } #endif /* CONFIG_DEBUG_FS */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) && defined(CONFIG_KALLSYMS) /* 75a66614db21007bcc8c37f9c5d5b922981387b9 was after 2.6.29 */ extern unsigned long kallsyms_addresses[]; EXTRACT_SYMBOL(kallsyms_addresses); extern unsigned long kallsyms_num_syms; EXTRACT_SYMBOL(kallsyms_num_syms); extern u8 kallsyms_names[]; EXTRACT_SYMBOL(kallsyms_names); static int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *, unsigned long), void *data) { char namebuf[KSYM_NAME_LEN]; unsigned long i; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) unsigned int off; #endif /* LINUX_VERSION_CODE */ int ret; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) for (i = 0, off = 0; i < kallsyms_num_syms; i++) { off = kallsyms_expand_symbol(off, namebuf); ret = fn(data, namebuf, NULL, kallsyms_addresses[i]); if (ret != 0) return ret; } #else /* LINUX_VERSION_CODE < */ /* 5648d78927ca65e74aadc88a2b1d6431e55e78ec was after 2.6.9 */ char *knames; for (i = 0, knames = kallsyms_names; i < kallsyms_num_syms; i++) { unsigned prefix = *knames++; strlcpy(namebuf + prefix, knames, KSYM_NAME_LEN - prefix); ret = fn(data, namebuf, NULL, kallsyms_addresses[i]); if (ret != OK) return ret; knames += strlen(knames) + 1; } #endif /* LINUX_VERSION_CODE */ return module_kallsyms_on_each_symbol(fn, data); } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) extern u8 kallsyms_token_table[]; EXTRACT_SYMBOL(kallsyms_token_table); extern u16 kallsyms_token_index[]; EXTRACT_SYMBOL(kallsyms_token_index); static unsigned int kallsyms_expand_symbol(unsigned int off, char *result) { long len, skipped_first = 0; const u8 *tptr, *data; data = &kallsyms_names[off]; len = *data; data++; off += len + 1; while (len) { tptr = &kallsyms_token_table[kallsyms_token_index[*data]]; data++; len--; while (*tptr) { if (skipped_first) { *result = *tptr; result++; } else skipped_first = 1; tptr++; } } *result = '\0'; return off; } #else /* LINUX_VERSION_CODE < */ /* 5648d78927ca65e74aadc88a2b1d6431e55e78ec was after 2.6.9 */ #endif /* LINUX_VERSION_CODE */ static int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *, unsigned long), void *data) { struct module *mod; unsigned int i; int ret; list_for_each_entry(mod, &modules, list) { for (i = 0; i < mod->num_symtab; i++) { ret = fn(data, mod->strtab + mod->symtab[i].st_name, mod, mod->symtab[i].st_value); if (ret != 0) return ret; } } return 0; } #endif /* LINUX_VERSION_CODE && CONFIG_KALLSYMS */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) /* c6b37801911d7f4663c99cad8aa230bc934cea82 was after 2.6.29 */ static struct module *find_module(const char *name) { struct module *mod; list_for_each_entry(mod, &modules, list) { if (strcmp(mod->name, name) == 0) return mod; } return NULL; } #ifdef CONFIG_MODULE_UNLOAD struct module_use { struct list_head list; struct module *module_which_uses; }; /* I'm not yet certain whether we need the strong form of this. */ static inline int strong_try_module_get(struct module *mod) { if (mod && mod->state != MODULE_STATE_LIVE) return -EBUSY; if (try_module_get(mod)) return 0; return -ENOENT; } /* Does a already use b? */ static int already_uses(struct module *a, struct module *b) { struct module_use *use; list_for_each_entry(use, &b->modules_which_use_me, list) { if (use->module_which_uses == a) return 1; } return 0; } /* Make it so module a uses b. Must be holding module_mutex */ static int use_module(struct module *a, struct module *b) { struct module_use *use; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) /* 270a6c4cad809e92d7b81adde92d0b3d94eeb8ee was after 2.6.20 */ int no_warn; #endif /* LINUX_VERSION_CODE */ if (b == NULL || already_uses(a, b)) return 1; if (strong_try_module_get(b) < 0) return 0; use = kmalloc(sizeof(*use), GFP_ATOMIC); if (!use) { module_put(b); return 0; } use->module_which_uses = a; list_add(&use->list, &b->modules_which_use_me); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) /* 270a6c4cad809e92d7b81adde92d0b3d94eeb8ee was after 2.6.20 */ no_warn = sysfs_create_link(b->holders_dir, &a->mkobj.kobj, a->name); #endif /* LINUX_VERSION_CODE */ return 1; } #else /* CONFIG_MODULE_UNLOAD */ static int use_module(struct module *a, struct module *b) { return 1; } #endif /* CONFIG_MODULE_UNLOAD */ #ifndef CONFIG_MODVERSIONS #define symversion(base, idx) NULL #else #define symversion(base, idx) ((base != NULL) ? ((base) + (idx)) : NULL) #endif static bool each_symbol_in_section(const struct symsearch *arr, unsigned int arrsize, struct module *owner, bool (*fn)(const struct symsearch *syms, struct module *owner, unsigned int symnum, void *data), void *data) { unsigned int i, j; for (j = 0; j < arrsize; j++) { for (i = 0; i < arr[j].stop - arr[j].start; i++) if (fn(&arr[j], owner, i, data)) return true; } return false; } /* Returns true as soon as fn returns true, otherwise false. */ static bool each_symbol(bool (*fn)(const struct symsearch *arr, struct module *owner, unsigned int symnum, void *data), void *data) { struct module *mod; const struct symsearch arr[] = { { __start___ksymtab, __stop___ksymtab, __start___kcrctab, NOT_GPL_ONLY, false }, { __start___ksymtab_gpl, __stop___ksymtab_gpl, __start___kcrctab_gpl, GPL_ONLY, false }, #ifdef KSPLICE_KSYMTAB_FUTURE_SUPPORT { __start___ksymtab_gpl_future, __stop___ksymtab_gpl_future, __start___kcrctab_gpl_future, WILL_BE_GPL_ONLY, false }, #endif /* KSPLICE_KSYMTAB_FUTURE_SUPPORT */ #ifdef KSPLICE_KSYMTAB_UNUSED_SUPPORT { __start___ksymtab_unused, __stop___ksymtab_unused, __start___kcrctab_unused, NOT_GPL_ONLY, true }, { __start___ksymtab_unused_gpl, __stop___ksymtab_unused_gpl, __start___kcrctab_unused_gpl, GPL_ONLY, true }, #endif /* KSPLICE_KSYMTAB_UNUSED_SUPPORT */ }; if (each_symbol_in_section(arr, ARRAY_SIZE(arr), NULL, fn, data)) return 1; list_for_each_entry(mod, &modules, list) { struct symsearch module_arr[] = { { mod->syms, mod->syms + mod->num_syms, mod->crcs, NOT_GPL_ONLY, false }, { mod->gpl_syms, mod->gpl_syms + mod->num_gpl_syms, mod->gpl_crcs, GPL_ONLY, false }, #ifdef KSPLICE_KSYMTAB_FUTURE_SUPPORT { mod->gpl_future_syms, mod->gpl_future_syms + mod->num_gpl_future_syms, mod->gpl_future_crcs, WILL_BE_GPL_ONLY, false }, #endif /* KSPLICE_KSYMTAB_FUTURE_SUPPORT */ #ifdef KSPLICE_KSYMTAB_UNUSED_SUPPORT { mod->unused_syms, mod->unused_syms + mod->num_unused_syms, mod->unused_crcs, NOT_GPL_ONLY, true }, { mod->unused_gpl_syms, mod->unused_gpl_syms + mod->num_unused_gpl_syms, mod->unused_gpl_crcs, GPL_ONLY, true }, #endif /* KSPLICE_KSYMTAB_UNUSED_SUPPORT */ }; if (each_symbol_in_section(module_arr, ARRAY_SIZE(module_arr), mod, fn, data)) return true; } return false; } struct find_symbol_arg { /* Input */ const char *name; bool gplok; bool warn; /* Output */ struct module *owner; const unsigned long *crc; const struct kernel_symbol *sym; }; static bool find_symbol_in_section(const struct symsearch *syms, struct module *owner, unsigned int symnum, void *data) { struct find_symbol_arg *fsa = data; if (strcmp(syms->start[symnum].name, fsa->name) != 0) return false; if (!fsa->gplok) { if (syms->licence == GPL_ONLY) return false; if (syms->licence == WILL_BE_GPL_ONLY && fsa->warn) { printk(KERN_WARNING "Symbol %s is being used " "by a non-GPL module, which will not " "be allowed in the future\n", fsa->name); printk(KERN_WARNING "Please see the file " "Documentation/feature-removal-schedule.txt " "in the kernel source tree for more details.\n"); } } #ifdef CONFIG_UNUSED_SYMBOLS if (syms->unused && fsa->warn) { printk(KERN_WARNING "Symbol %s is marked as UNUSED, " "however this module is using it.\n", fsa->name); printk(KERN_WARNING "This symbol will go away in the future.\n"); printk(KERN_WARNING "Please evalute if this is the right api to use and if " "it really is, submit a report the linux kernel " "mailinglist together with submitting your code for " "inclusion.\n"); } #endif fsa->owner = owner; fsa->crc = symversion(syms->crcs, symnum); fsa->sym = &syms->start[symnum]; return true; } /* Find a symbol and return it, along with, (optional) crc and * (optional) module which owns it */ static const struct kernel_symbol *find_symbol(const char *name, struct module **owner, const unsigned long **crc, bool gplok, bool warn) { struct find_symbol_arg fsa; fsa.name = name; fsa.gplok = gplok; fsa.warn = warn; if (each_symbol(find_symbol_in_section, &fsa)) { if (owner) *owner = fsa.owner; if (crc) *crc = fsa.crc; return fsa.sym; } return NULL; } static inline int within_module_core(unsigned long addr, struct module *mod) { return (unsigned long)mod->module_core <= addr && addr < (unsigned long)mod->module_core + mod->core_size; } static inline int within_module_init(unsigned long addr, struct module *mod) { return (unsigned long)mod->module_init <= addr && addr < (unsigned long)mod->module_init + mod->init_size; } static struct module *__module_address(unsigned long addr) { struct module *mod; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) list_for_each_entry_rcu(mod, &modules, list) #else /* d72b37513cdfbd3f53f3d485a8c403cc96d2c95f was after 2.6.27 */ list_for_each_entry(mod, &modules, list) #endif if (within_module_core(addr, mod) || within_module_init(addr, mod)) return mod; return NULL; } #endif /* LINUX_VERSION_CODE */ struct update_attribute { struct attribute attr; ssize_t (*show)(struct update *update, char *buf); ssize_t (*store)(struct update *update, const char *buf, size_t len); }; static ssize_t update_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) { struct update_attribute *attribute = container_of(attr, struct update_attribute, attr); struct update *update = container_of(kobj, struct update, kobj); if (attribute->show == NULL) return -EIO; return attribute->show(update, buf); } static ssize_t update_attr_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t len) { struct update_attribute *attribute = container_of(attr, struct update_attribute, attr); struct update *update = container_of(kobj, struct update, kobj); if (attribute->store == NULL) return -EIO; return attribute->store(update, buf, len); } static struct sysfs_ops update_sysfs_ops = { .show = update_attr_show, .store = update_attr_store, }; static void update_release(struct kobject *kobj) { struct update *update; update = container_of(kobj, struct update, kobj); cleanup_ksplice_update(update); } static ssize_t stage_show(struct update *update, char *buf) { switch (update->stage) { case STAGE_PREPARING: return snprintf(buf, PAGE_SIZE, "preparing\n"); case STAGE_APPLIED: return snprintf(buf, PAGE_SIZE, "applied\n"); case STAGE_REVERSED: return snprintf(buf, PAGE_SIZE, "reversed\n"); } return 0; } static ssize_t abort_cause_show(struct update *update, char *buf) { switch (update->abort_cause) { case OK: return snprintf(buf, PAGE_SIZE, "ok\n"); case NO_MATCH: return snprintf(buf, PAGE_SIZE, "no_match\n"); #ifdef KSPLICE_STANDALONE case BAD_SYSTEM_MAP: return snprintf(buf, PAGE_SIZE, "bad_system_map\n"); #endif /* KSPLICE_STANDALONE */ case CODE_BUSY: return snprintf(buf, PAGE_SIZE, "code_busy\n"); case MODULE_BUSY: return snprintf(buf, PAGE_SIZE, "module_busy\n"); case OUT_OF_MEMORY: return snprintf(buf, PAGE_SIZE, "out_of_memory\n"); case FAILED_TO_FIND: return snprintf(buf, PAGE_SIZE, "failed_to_find\n"); case ALREADY_REVERSED: return snprintf(buf, PAGE_SIZE, "already_reversed\n"); case MISSING_EXPORT: return snprintf(buf, PAGE_SIZE, "missing_export\n"); case UNEXPECTED_RUNNING_TASK: return snprintf(buf, PAGE_SIZE, "unexpected_running_task\n"); case TARGET_NOT_LOADED: return snprintf(buf, PAGE_SIZE, "target_not_loaded\n"); case CALL_FAILED: return snprintf(buf, PAGE_SIZE, "call_failed\n"); case COLD_UPDATE_LOADED: return snprintf(buf, PAGE_SIZE, "cold_update_loaded\n"); case UNEXPECTED: return snprintf(buf, PAGE_SIZE, "unexpected\n"); default: return snprintf(buf, PAGE_SIZE, "unknown\n"); } return 0; } static ssize_t conflict_show(struct update *update, char *buf) { const struct conflict *conf; const struct conflict_addr *ca; int lastused = 0; mutex_lock(&module_mutex); list_for_each_entry(conf, &update->conflicts, list) { int used = lastused; used += snprintf(buf + used, PAGE_SIZE - used, "%s %d", conf->process_name, conf->pid); if (used >= PAGE_SIZE) goto out; list_for_each_entry(ca, &conf->stack, list) { if (!ca->has_conflict) continue; used += snprintf(buf + used, PAGE_SIZE - used, " %s", ca->label); if (used >= PAGE_SIZE) goto out; } used += snprintf(buf + used, PAGE_SIZE - used, "\n"); if (used >= PAGE_SIZE) goto out; lastused = used; } out: mutex_unlock(&module_mutex); return lastused; } /* Used to pass maybe_cleanup_ksplice_update to kthread_run */ static int maybe_cleanup_ksplice_update_wrapper(void *updateptr) { struct update *update = updateptr; mutex_lock(&module_mutex); maybe_cleanup_ksplice_update(update); mutex_unlock(&module_mutex); return 0; } static ssize_t stage_store(struct update *update, const char *buf, size_t len) { enum stage old_stage; mutex_lock(&module_mutex); old_stage = update->stage; if ((strncmp(buf, "applied", len) == 0 || strncmp(buf, "applied\n", len) == 0) && update->stage == STAGE_PREPARING) update->abort_cause = apply_update(update); else if ((strncmp(buf, "reversed", len) == 0 || strncmp(buf, "reversed\n", len) == 0) && update->stage == STAGE_APPLIED) update->abort_cause = reverse_update(update); else if ((strncmp(buf, "cleanup", len) == 0 || strncmp(buf, "cleanup\n", len) == 0) && update->stage == STAGE_REVERSED) kthread_run(maybe_cleanup_ksplice_update_wrapper, update, "ksplice_cleanup_%s", update->kid); mutex_unlock(&module_mutex); return len; } static ssize_t debug_show(struct update *update, char *buf) { return snprintf(buf, PAGE_SIZE, "%d\n", update->debug); } static ssize_t debug_store(struct update *update, const char *buf, size_t len) { unsigned long l; int ret = strict_strtoul(buf, 10, &l); if (ret != 0) return ret; update->debug = l; return len; } static ssize_t partial_show(struct update *update, char *buf) { return snprintf(buf, PAGE_SIZE, "%d\n", update->partial); } static ssize_t partial_store(struct update *update, const char *buf, size_t len) { unsigned long l; int ret = strict_strtoul(buf, 10, &l); if (ret != 0) return ret; update->partial = l; return len; } static struct update_attribute stage_attribute = __ATTR(stage, 0600, stage_show, stage_store); static struct update_attribute abort_cause_attribute = __ATTR(abort_cause, 0400, abort_cause_show, NULL); static struct update_attribute debug_attribute = __ATTR(debug, 0600, debug_show, debug_store); static struct update_attribute partial_attribute = __ATTR(partial, 0600, partial_show, partial_store); static struct update_attribute conflict_attribute = __ATTR(conflicts, 0400, conflict_show, NULL); static struct attribute *update_attrs[] = { &stage_attribute.attr, &abort_cause_attribute.attr, &debug_attribute.attr, &partial_attribute.attr, &conflict_attribute.attr, NULL }; static struct kobj_type update_ktype = { .sysfs_ops = &update_sysfs_ops, .release = update_release, .default_attrs = update_attrs, }; #ifdef KSPLICE_STANDALONE static int debug; module_param(debug, int, 0600); MODULE_PARM_DESC(debug, "Debug level"); extern struct ksplice_system_map ksplice_system_map[], ksplice_system_map_end[]; static struct ksplice_mod_change bootstrap_mod_change = { .name = "ksplice_" __stringify(KSPLICE_KID), .kid = "init_" __stringify(KSPLICE_KID), .target_name = NULL, .target = NULL, .map_printk = MAP_PRINTK, .new_code_mod = THIS_MODULE, .new_code.system_map = ksplice_system_map, .new_code.system_map_end = ksplice_system_map_end, }; #endif /* KSPLICE_STANDALONE */ static int init_ksplice(void) { #ifdef KSPLICE_STANDALONE struct ksplice_mod_change *change = &bootstrap_mod_change; change->update = init_ksplice_update(change->kid); sort(change->new_code.system_map, change->new_code.system_map_end - change->new_code.system_map, sizeof(struct ksplice_system_map), compare_system_map, NULL); if (change->update == NULL) return -ENOMEM; add_to_update(change, change->update); change->update->debug = debug; change->update->abort_cause = apply_relocs(change, ksplice_init_relocs, ksplice_init_relocs_end); if (change->update->abort_cause == OK) bootstrapped = true; cleanup_ksplice_update(bootstrap_mod_change.update); #else /* !KSPLICE_STANDALONE */ ksplice_kobj = kobject_create_and_add("ksplice", kernel_kobj); if (ksplice_kobj == NULL) return -ENOMEM; #endif /* KSPLICE_STANDALONE */ return 0; } static void cleanup_ksplice(void) { #ifndef KSPLICE_STANDALONE kobject_put(ksplice_kobj); #endif /* KSPLICE_STANDALONE */ } module_init(init_ksplice); module_exit(cleanup_ksplice); MODULE_AUTHOR("Ksplice, Inc."); MODULE_DESCRIPTION("Ksplice rebootless update system"); #ifdef KSPLICE_VERSION MODULE_VERSION(KSPLICE_VERSION); #endif MODULE_LICENSE("GPL v2"); ksplice-0.9.9/kmodsrc/old_code_loader.c0000644000000000000000000000444311244274432016575 0ustar rootroot/* Copyright (C) 2007-2009 Ksplice, Inc. * Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA * 02110-1301, USA. */ #ifdef KSPLICE_STANDALONE #include "ksplice.h" #else #include #endif extern struct ksplice_reloc ksplice_relocs[], ksplice_relocs_end[]; extern struct ksplice_section ksplice_sections[], ksplice_sections_end[]; extern struct ksplice_symbol ksplice_symbols[], ksplice_symbols_end[]; #ifdef KSPLICE_NEED_PARAINSTRUCTIONS extern struct paravirt_patch_site parainstructions[], parainstructions_end[]; #endif #ifdef KSPLICE_STANDALONE extern struct ksplice_system_map ksplice_system_map[], ksplice_system_map_end[]; #endif /* KSPLICE_STANDALONE */ /* Defined in new_code_loader.c */ #define change KSPLICE_UNIQ(change) extern struct ksplice_mod_change change; static struct ksplice_code old_code = { .relocs = ksplice_relocs, .relocs_end = ksplice_relocs_end, .sections = ksplice_sections, .sections_end = ksplice_sections_end, .symbols = ksplice_symbols, .symbols_end = ksplice_symbols_end, #ifdef KSPLICE_NEED_PARAINSTRUCTIONS .parainstructions = parainstructions, .parainstructions_end = parainstructions_end, #endif #ifdef KSPLICE_STANDALONE .system_map = ksplice_system_map, .system_map_end = ksplice_system_map_end, #endif /* KSPLICE_STANDALONE */ }; static int init_old_code(void) { change.old_code = old_code; return init_ksplice_mod_change(&change); } static void cleanup_old_code(void) { cleanup_ksplice_mod_change(&change); } module_init(init_old_code); module_exit(cleanup_old_code); MODULE_AUTHOR("Ksplice, Inc."); MODULE_DESCRIPTION("Ksplice rebootless update old code module"); #ifdef KSPLICE_VERSION MODULE_VERSION(KSPLICE_VERSION); #endif MODULE_LICENSE("GPL v2"); ksplice-0.9.9/kmodsrc/arm/0000755000000000000000000000000011244274432014105 5ustar rootrootksplice-0.9.9/kmodsrc/arm/ksplice-arch.c0000644000000000000000000000445111244274432016622 0ustar rootroot/* Copyright (C) 2007-2009 Ksplice, Inc. * Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA * 02110-1301, USA. */ #include #define KSPLICE_IP(x) thread_saved_pc(x) #define KSPLICE_SP(x) thread_saved_fp(x) static struct ksplice_symbol trampoline_symbol = { .name = NULL, .label = "", }; static const struct ksplice_reloc_howto trampoline_howto = { .type = KSPLICE_HOWTO_RELOC, .pcrel = 1, .size = 4, .dst_mask = 0x00ffffffL, .rightshift = 2, .signed_addend = 1, }; static const struct ksplice_reloc trampoline_reloc = { .symbol = &trampoline_symbol, .insn_addend = -8, .target_addend = 0, .howto = &trampoline_howto, }; static abort_t trampoline_target(struct ksplice_mod_change *change, unsigned long addr, unsigned long *new_addr) { abort_t ret; uint32_t word; if (probe_kernel_read(&word, (void *)addr, sizeof(word)) == -EFAULT) return NO_MATCH; if ((word & 0xff000000) != 0xea000000) return NO_MATCH; ret = read_reloc_value(change, &trampoline_reloc, addr, new_addr); if (ret != OK) return ret; *new_addr += addr; return OK; } static abort_t prepare_trampoline(struct ksplice_mod_change *change, struct ksplice_patch *p) { p->size = 4; *(uint32_t *)p->contents = 0xea000000; return write_reloc_value(change, &trampoline_reloc, (unsigned long)p->contents, p->repladdr - p->oldaddr); } static abort_t handle_paravirt(struct ksplice_mod_change *change, unsigned long pre_addr, unsigned long run_addr, int *matched) { *matched = 0; return OK; } static bool valid_stack_ptr(const struct thread_info *tinfo, const void *p) { return p > (const void *)tinfo && p <= (const void *)tinfo + THREAD_SIZE - sizeof(long); } ksplice-0.9.9/kmodsrc/ksplice.lds.S0000644000000000000000000000155011244274432015666 0ustar rootroot#define PTR_KEEP_SQUASH(section) \ .##section : { \ section = .; \ KEEP(*(.##section##*)) \ section##_end = .; \ } #define PTR_KEEP(section) \ .##section : { \ section = .; \ KEEP(*(.##section)) \ section##_end = .; \ } SECTIONS { .text : { *(.text .text.* .exit.text .sched.text) } PTR_KEEP_SQUASH(ksplice_relocs) PTR_KEEP_SQUASH(ksplice_sections) PTR_KEEP_SQUASH(ksplice_patches) PTR_KEEP(ksplice_symbols) PTR_KEEP(ksplice_system_map) PTR_KEEP(ksplice_call_pre_apply) PTR_KEEP(ksplice_call_check_apply) PTR_KEEP(ksplice_call_apply) PTR_KEEP(ksplice_call_post_apply) PTR_KEEP(ksplice_call_fail_apply) PTR_KEEP(ksplice_call_pre_reverse) PTR_KEEP(ksplice_call_check_reverse) PTR_KEEP(ksplice_call_reverse) PTR_KEEP(ksplice_call_post_reverse) PTR_KEEP(ksplice_call_fail_reverse) PTR_KEEP(parainstructions) } ksplice-0.9.9/kmodsrc/x86/0000755000000000000000000000000011244274432013753 5ustar rootrootksplice-0.9.9/kmodsrc/x86/udis86.h0000644000000000000000000000302211244274432015243 0ustar rootroot/* udis86 - udis86.h * * Copyright (c) 2002-2009 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef UDIS86_H #define UDIS86_H #include "libudis86/types.h" #include "libudis86/extern.h" #include "libudis86/itab.h" #endif ksplice-0.9.9/kmodsrc/x86/libudis86/0000755000000000000000000000000011244274432015564 5ustar rootrootksplice-0.9.9/kmodsrc/x86/libudis86/syn-intel.c0000644000000000000000000001357511206570615017665 0ustar rootroot/* udis86 - libudis86/syn-intel.c * * Copyright (c) 2002-2009 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "types.h" #include "extern.h" #include "decode.h" #include "itab.h" #include "syn.h" /* ----------------------------------------------------------------------------- * opr_cast() - Prints an operand cast. * ----------------------------------------------------------------------------- */ static void opr_cast(struct ud* u, struct ud_operand* op) { switch(op->size) { case 8: mkasm(u, "byte " ); break; case 16: mkasm(u, "word " ); break; case 32: mkasm(u, "dword "); break; case 64: mkasm(u, "qword "); break; case 80: mkasm(u, "tword "); break; default: break; } if (u->br_far) mkasm(u, "far "); else if (u->br_near) mkasm(u, "near "); } /* ----------------------------------------------------------------------------- * gen_operand() - Generates assembly output for each operand. * ----------------------------------------------------------------------------- */ static void gen_operand(struct ud* u, struct ud_operand* op, int syn_cast) { switch(op->type) { case UD_OP_REG: mkasm(u, ud_reg_tab[op->base - UD_R_AL]); break; case UD_OP_MEM: { int op_f = 0; if (syn_cast) opr_cast(u, op); mkasm(u, "["); if (u->pfx_seg) mkasm(u, "%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]); if (op->base) { mkasm(u, "%s", ud_reg_tab[op->base - UD_R_AL]); op_f = 1; } if (op->index) { if (op_f) mkasm(u, "+"); mkasm(u, "%s", ud_reg_tab[op->index - UD_R_AL]); op_f = 1; } if (op->scale) mkasm(u, "*%d", op->scale); if (op->offset == 8) { if (op->lval.sbyte < 0) mkasm(u, "-0x%x", -op->lval.sbyte); else mkasm(u, "%s0x%x", (op_f) ? "+" : "", op->lval.sbyte); } else if (op->offset == 16) mkasm(u, "%s0x%x", (op_f) ? "+" : "", op->lval.uword); else if (op->offset == 32) { if (u->adr_mode == 64) { if (op->lval.sdword < 0) mkasm(u, "-0x%x", -op->lval.sdword); else mkasm(u, "%s0x%x", (op_f) ? "+" : "", op->lval.sdword); } else mkasm(u, "%s0x%lx", (op_f) ? "+" : "", op->lval.udword); } else if (op->offset == 64) mkasm(u, "%s0x" FMT64 "x", (op_f) ? "+" : "", op->lval.uqword); mkasm(u, "]"); break; } case UD_OP_IMM: if (syn_cast) opr_cast(u, op); switch (op->size) { case 8: mkasm(u, "0x%x", op->lval.ubyte); break; case 16: mkasm(u, "0x%x", op->lval.uword); break; case 32: mkasm(u, "0x%lx", op->lval.udword); break; case 64: mkasm(u, "0x" FMT64 "x", op->lval.uqword); break; default: break; } break; case UD_OP_JIMM: if (syn_cast) opr_cast(u, op); switch (op->size) { case 8: mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sbyte); break; case 16: mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sword); break; case 32: mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sdword); break; default:break; } break; case UD_OP_PTR: switch (op->size) { case 32: mkasm(u, "word 0x%x:0x%x", op->lval.ptr.seg, op->lval.ptr.off & 0xFFFF); break; case 48: mkasm(u, "dword 0x%x:0x%lx", op->lval.ptr.seg, op->lval.ptr.off); break; } break; case UD_OP_CONST: if (syn_cast) opr_cast(u, op); mkasm(u, "%d", op->lval.udword); break; default: return; } } /* ============================================================================= * translates to intel syntax * ============================================================================= */ extern void ud_translate_intel(struct ud* u) { /* -- prefixes -- */ /* check if P_OSO prefix is used */ if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) { switch (u->dis_mode) { case 16: mkasm(u, "o32 "); break; case 32: case 64: mkasm(u, "o16 "); break; } } /* check if P_ASO prefix was used */ if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) { switch (u->dis_mode) { case 16: mkasm(u, "a32 "); break; case 32: mkasm(u, "a16 "); break; case 64: mkasm(u, "a32 "); break; } } if (u->pfx_lock) mkasm(u, "lock "); if (u->pfx_rep) mkasm(u, "rep "); if (u->pfx_repne) mkasm(u, "repne "); if (u->implicit_addr && u->pfx_seg) mkasm(u, "%s ", ud_reg_tab[u->pfx_seg - UD_R_AL]); /* print the instruction mnemonic */ mkasm(u, "%s ", ud_lookup_mnemonic(u->mnemonic)); /* operand 1 */ if (u->operand[0].type != UD_NONE) { gen_operand(u, &u->operand[0], u->c1); } /* operand 2 */ if (u->operand[1].type != UD_NONE) { mkasm(u, ", "); gen_operand(u, &u->operand[1], u->c2); } /* operand 3 */ if (u->operand[2].type != UD_NONE) { mkasm(u, ", "); gen_operand(u, &u->operand[2], u->c3); } } ksplice-0.9.9/kmodsrc/x86/libudis86/decode.h0000644000000000000000000001277511225645327017200 0ustar rootroot/* udis86 - libudis86/decode.h * * Copyright (c) 2002-2009 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef UD_DECODE_H #define UD_DECODE_H #define MAX_INSN_LENGTH 15 /* register classes */ #define T_NONE 0 #define T_GPR 1 #define T_MMX 2 #define T_CRG 3 #define T_DBG 4 #define T_SEG 5 #define T_XMM 6 /* itab prefix bits */ #define P_none ( 0 ) #define P_c1 ( 1 << 0 ) #define P_C1(n) ( ( n >> 0 ) & 1 ) #define P_rexb ( 1 << 1 ) #define P_REXB(n) ( ( n >> 1 ) & 1 ) #define P_depM ( 1 << 2 ) #define P_DEPM(n) ( ( n >> 2 ) & 1 ) #define P_c3 ( 1 << 3 ) #define P_C3(n) ( ( n >> 3 ) & 1 ) #define P_inv64 ( 1 << 4 ) #define P_INV64(n) ( ( n >> 4 ) & 1 ) #define P_rexw ( 1 << 5 ) #define P_REXW(n) ( ( n >> 5 ) & 1 ) #define P_c2 ( 1 << 6 ) #define P_C2(n) ( ( n >> 6 ) & 1 ) #define P_def64 ( 1 << 7 ) #define P_DEF64(n) ( ( n >> 7 ) & 1 ) #define P_rexr ( 1 << 8 ) #define P_REXR(n) ( ( n >> 8 ) & 1 ) #define P_oso ( 1 << 9 ) #define P_OSO(n) ( ( n >> 9 ) & 1 ) #define P_aso ( 1 << 10 ) #define P_ASO(n) ( ( n >> 10 ) & 1 ) #define P_rexx ( 1 << 11 ) #define P_REXX(n) ( ( n >> 11 ) & 1 ) #define P_ImpAddr ( 1 << 12 ) #define P_IMPADDR(n) ( ( n >> 12 ) & 1 ) /* rex prefix bits */ #define REX_W(r) ( ( 0xF & ( r ) ) >> 3 ) #define REX_R(r) ( ( 0x7 & ( r ) ) >> 2 ) #define REX_X(r) ( ( 0x3 & ( r ) ) >> 1 ) #define REX_B(r) ( ( 0x1 & ( r ) ) >> 0 ) #define REX_PFX_MASK(n) ( ( P_REXW(n) << 3 ) | \ ( P_REXR(n) << 2 ) | \ ( P_REXX(n) << 1 ) | \ ( P_REXB(n) << 0 ) ) /* scable-index-base bits */ #define SIB_S(b) ( ( b ) >> 6 ) #define SIB_I(b) ( ( ( b ) >> 3 ) & 7 ) #define SIB_B(b) ( ( b ) & 7 ) /* modrm bits */ #define MODRM_REG(b) ( ( ( b ) >> 3 ) & 7 ) #define MODRM_NNN(b) ( ( ( b ) >> 3 ) & 7 ) #define MODRM_MOD(b) ( ( ( b ) >> 6 ) & 3 ) #define MODRM_RM(b) ( ( b ) & 7 ) /* operand type constants -- order is important! */ enum ud_operand_code { OP_NONE, OP_A, OP_E, OP_M, OP_G, OP_I, OP_AL, OP_CL, OP_DL, OP_BL, OP_AH, OP_CH, OP_DH, OP_BH, OP_ALr8b, OP_CLr9b, OP_DLr10b, OP_BLr11b, OP_AHr12b, OP_CHr13b, OP_DHr14b, OP_BHr15b, OP_AX, OP_CX, OP_DX, OP_BX, OP_SI, OP_DI, OP_SP, OP_BP, OP_rAX, OP_rCX, OP_rDX, OP_rBX, OP_rSP, OP_rBP, OP_rSI, OP_rDI, OP_rAXr8, OP_rCXr9, OP_rDXr10, OP_rBXr11, OP_rSPr12, OP_rBPr13, OP_rSIr14, OP_rDIr15, OP_eAX, OP_eCX, OP_eDX, OP_eBX, OP_eSP, OP_eBP, OP_eSI, OP_eDI, OP_ES, OP_CS, OP_SS, OP_DS, OP_FS, OP_GS, OP_ST0, OP_ST1, OP_ST2, OP_ST3, OP_ST4, OP_ST5, OP_ST6, OP_ST7, OP_J, OP_S, OP_O, OP_I1, OP_I3, OP_V, OP_W, OP_Q, OP_P, OP_R, OP_C, OP_D, OP_VR, OP_PR } UD_ATTR_PACKED; /* operand size constants */ enum ud_operand_size { SZ_NA = 0, SZ_Z = 1, SZ_V = 2, SZ_P = 3, SZ_WP = 4, SZ_DP = 5, SZ_MDQ = 6, SZ_RDQ = 7, /* the following values are used as is, * and thus hard-coded. changing them * will break internals */ SZ_B = 8, SZ_W = 16, SZ_D = 32, SZ_Q = 64, SZ_T = 80, SZ_O = 128, } UD_ATTR_PACKED; /* A single operand of an entry in the instruction table. * (internal use only) */ struct ud_itab_entry_operand { enum ud_operand_code type; enum ud_operand_size size; }; /* A single entry in an instruction table. *(internal use only) */ struct ud_itab_entry { enum ud_mnemonic_code mnemonic; struct ud_itab_entry_operand operand1; struct ud_itab_entry_operand operand2; struct ud_itab_entry_operand operand3; uint32_t prefix; }; extern const char * ud_lookup_mnemonic( enum ud_mnemonic_code c ); #endif /* UD_DECODE_H */ /* vim:cindent * vim:expandtab * vim:ts=4 * vim:sw=4 */ ksplice-0.9.9/kmodsrc/x86/libudis86/syn.c0000644000000000000000000000543111206570615016544 0ustar rootroot/* udis86 - libudis86/syn.c * * Copyright (c) 2002-2009 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* ----------------------------------------------------------------------------- * Intel Register Table - Order Matters (types.h)! * ----------------------------------------------------------------------------- */ const char* ud_reg_tab[] = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", "spl", "bpl", "sil", "dil", "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b", "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "r8w", "r9w", "r10w", "r11w", "r12w", "r13W" , "r14w", "r15w", "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d", "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "es", "cs", "ss", "ds", "fs", "gs", "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", "cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15", "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7", "dr8", "dr9", "dr10", "dr11", "dr12", "dr13", "dr14", "dr15", "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", "st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "rip" }; ksplice-0.9.9/kmodsrc/x86/libudis86/syn.h0000644000000000000000000000400711206570615016547 0ustar rootroot/* udis86 - libudis86/syn.h * * Copyright (c) 2002-2009 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* ----------------------------------------------------------------------------- * syn.h * * Copyright (c) 2006, Vivek Mohan * All rights reserved. See LICENSE * ----------------------------------------------------------------------------- */ #ifndef UD_SYN_H #define UD_SYN_H #include "types.h" #ifndef __UD_STANDALONE__ # include #endif /* __UD_STANDALONE__ */ extern const char* ud_reg_tab[]; static void mkasm(struct ud* u, const char* fmt, ...) { va_list ap; va_start(ap, fmt); u->insn_fill += vsprintf((char*) u->insn_buffer + u->insn_fill, fmt, ap); va_end(ap); } #endif ksplice-0.9.9/kmodsrc/x86/libudis86/Makefile0000644000000000000000000000016511206570615017226 0ustar rootrootobj-m += kudis86.o kudis86-objs += \ itab.o \ input.o \ decode.o \ syn.o \ syn-intel.o \ syn-att.o \ udis86.o ksplice-0.9.9/kmodsrc/x86/libudis86/types.h0000644000000000000000000001552711225645327017117 0ustar rootroot/* udis86 - libudis86/types.h * * Copyright (c) 2002-2009 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef UD_TYPES_H #define UD_TYPES_H #ifdef __KERNEL__ /* -D__KERNEL__ is automatically passed on the command line when building something as part of the Linux kernel */ # include # include # define __UD_STANDALONE__ 1 #endif /* __KERNEL__ */ #ifndef __UD_STANDALONE__ # include #endif /* __UD_STANDALONE__ */ /* gcc specific extensions */ #ifdef __GNUC__ # define UD_ATTR_PACKED __attribute__((packed)) #else # define UD_ATTR_PACKED #endif /* UD_ATTR_PACKED */ #ifdef _MSC_VER # define FMT64 "%I64" typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; typedef __int8 int8_t; typedef __int16 int16_t; typedef __int32 int32_t; typedef __int64 int64_t; #else # define FMT64 "%ll" # ifndef __UD_STANDALONE__ # include # endif /* __UD_STANDALONE__ */ #endif /* ----------------------------------------------------------------------------- * All possible "types" of objects in udis86. Order is Important! * ----------------------------------------------------------------------------- */ enum ud_type { UD_NONE, /* 8 bit GPRs */ UD_R_AL, UD_R_CL, UD_R_DL, UD_R_BL, UD_R_AH, UD_R_CH, UD_R_DH, UD_R_BH, UD_R_SPL, UD_R_BPL, UD_R_SIL, UD_R_DIL, UD_R_R8B, UD_R_R9B, UD_R_R10B, UD_R_R11B, UD_R_R12B, UD_R_R13B, UD_R_R14B, UD_R_R15B, /* 16 bit GPRs */ UD_R_AX, UD_R_CX, UD_R_DX, UD_R_BX, UD_R_SP, UD_R_BP, UD_R_SI, UD_R_DI, UD_R_R8W, UD_R_R9W, UD_R_R10W, UD_R_R11W, UD_R_R12W, UD_R_R13W, UD_R_R14W, UD_R_R15W, /* 32 bit GPRs */ UD_R_EAX, UD_R_ECX, UD_R_EDX, UD_R_EBX, UD_R_ESP, UD_R_EBP, UD_R_ESI, UD_R_EDI, UD_R_R8D, UD_R_R9D, UD_R_R10D, UD_R_R11D, UD_R_R12D, UD_R_R13D, UD_R_R14D, UD_R_R15D, /* 64 bit GPRs */ UD_R_RAX, UD_R_RCX, UD_R_RDX, UD_R_RBX, UD_R_RSP, UD_R_RBP, UD_R_RSI, UD_R_RDI, UD_R_R8, UD_R_R9, UD_R_R10, UD_R_R11, UD_R_R12, UD_R_R13, UD_R_R14, UD_R_R15, /* segment registers */ UD_R_ES, UD_R_CS, UD_R_SS, UD_R_DS, UD_R_FS, UD_R_GS, /* control registers*/ UD_R_CR0, UD_R_CR1, UD_R_CR2, UD_R_CR3, UD_R_CR4, UD_R_CR5, UD_R_CR6, UD_R_CR7, UD_R_CR8, UD_R_CR9, UD_R_CR10, UD_R_CR11, UD_R_CR12, UD_R_CR13, UD_R_CR14, UD_R_CR15, /* debug registers */ UD_R_DR0, UD_R_DR1, UD_R_DR2, UD_R_DR3, UD_R_DR4, UD_R_DR5, UD_R_DR6, UD_R_DR7, UD_R_DR8, UD_R_DR9, UD_R_DR10, UD_R_DR11, UD_R_DR12, UD_R_DR13, UD_R_DR14, UD_R_DR15, /* mmx registers */ UD_R_MM0, UD_R_MM1, UD_R_MM2, UD_R_MM3, UD_R_MM4, UD_R_MM5, UD_R_MM6, UD_R_MM7, /* x87 registers */ UD_R_ST0, UD_R_ST1, UD_R_ST2, UD_R_ST3, UD_R_ST4, UD_R_ST5, UD_R_ST6, UD_R_ST7, /* extended multimedia registers */ UD_R_XMM0, UD_R_XMM1, UD_R_XMM2, UD_R_XMM3, UD_R_XMM4, UD_R_XMM5, UD_R_XMM6, UD_R_XMM7, UD_R_XMM8, UD_R_XMM9, UD_R_XMM10, UD_R_XMM11, UD_R_XMM12, UD_R_XMM13, UD_R_XMM14, UD_R_XMM15, UD_R_RIP, /* Operand Types */ UD_OP_REG, UD_OP_MEM, UD_OP_PTR, UD_OP_IMM, UD_OP_JIMM, UD_OP_CONST }; #include "itab.h" /* ----------------------------------------------------------------------------- * struct ud_operand - Disassembled instruction Operand. * ----------------------------------------------------------------------------- */ struct ud_operand { enum ud_type type; uint8_t size; union { int8_t sbyte; uint8_t ubyte; int16_t sword; uint16_t uword; int32_t sdword; uint32_t udword; int64_t sqword; uint64_t uqword; struct { uint16_t seg; uint32_t off; } ptr; } lval; enum ud_type base; enum ud_type index; uint8_t offset; uint8_t scale; }; /* ----------------------------------------------------------------------------- * struct ud - The udis86 object. * ----------------------------------------------------------------------------- */ struct ud { int (*inp_hook) (struct ud*); uint8_t inp_curr; uint8_t inp_fill; #ifndef __UD_STANDALONE__ FILE* inp_file; #endif uint8_t inp_ctr; uint8_t* inp_buff; uint8_t* inp_buff_end; uint8_t inp_end; void (*translator)(struct ud*); uint64_t insn_offset; char insn_hexcode[32]; char insn_buffer[64]; unsigned int insn_fill; uint8_t dis_mode; uint64_t pc; uint8_t vendor; struct map_entry* mapen; enum ud_mnemonic_code mnemonic; struct ud_operand operand[3]; uint8_t error; uint8_t pfx_rex; uint8_t pfx_seg; uint8_t pfx_opr; uint8_t pfx_adr; uint8_t pfx_lock; uint8_t pfx_rep; uint8_t pfx_repe; uint8_t pfx_repne; uint8_t pfx_insn; uint8_t default64; uint8_t opr_mode; uint8_t adr_mode; uint8_t br_far; uint8_t br_near; uint8_t implicit_addr; uint8_t c1; uint8_t c2; uint8_t c3; uint8_t inp_cache[256]; uint8_t inp_sess[64]; void * user_opaque_data; struct ud_itab_entry * itab_entry; }; /* ----------------------------------------------------------------------------- * Type-definitions * ----------------------------------------------------------------------------- */ typedef enum ud_type ud_type_t; typedef enum ud_mnemonic_code ud_mnemonic_code_t; typedef struct ud ud_t; typedef struct ud_operand ud_operand_t; #define UD_SYN_INTEL ud_translate_intel #define UD_SYN_ATT ud_translate_att #define UD_EOI -1 #define UD_INP_CACHE_SZ 32 #define UD_VENDOR_AMD 0 #define UD_VENDOR_INTEL 1 #define UD_VENDOR_ANY 2 #define bail_out(ud,error_code) longjmp( (ud)->bailout, error_code ) #define try_decode(ud) if ( setjmp( (ud)->bailout ) == 0 ) #define catch_error() else #endif ksplice-0.9.9/kmodsrc/x86/libudis86/decode.c0000644000000000000000000010667011206570615017165 0ustar rootroot/* udis86 - libudis86/decode.c * * Copyright (c) 2002-2009 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "types.h" #include "itab.h" #include "input.h" #include "decode.h" #ifndef __UD_STANDALONE__ # include #endif /* __UD_STANDALONE__ */ /* The max number of prefixes to an instruction */ #define MAX_PREFIXES 15 static struct ud_itab_entry ie_invalid = { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }; static struct ud_itab_entry ie_pause = { UD_Ipause, O_NONE, O_NONE, O_NONE, P_none }; static struct ud_itab_entry ie_nop = { UD_Inop, O_NONE, O_NONE, O_NONE, P_none }; /* Looks up mnemonic code in the mnemonic string table * Returns NULL if the mnemonic code is invalid */ const char * ud_lookup_mnemonic( enum ud_mnemonic_code c ) { if ( c < UD_Id3vil ) return ud_mnemonics_str[ c ]; return NULL; } /* Extracts instruction prefixes. */ static int get_prefixes( struct ud* u ) { unsigned int have_pfx = 1; unsigned int i; uint8_t curr; /* if in error state, bail out */ if ( u->error ) return -1; /* keep going as long as there are prefixes available */ for ( i = 0; have_pfx ; ++i ) { /* Get next byte. */ inp_next(u); if ( u->error ) return -1; curr = inp_curr( u ); /* rex prefixes in 64bit mode */ if ( u->dis_mode == 64 && ( curr & 0xF0 ) == 0x40 ) { u->pfx_rex = curr; } else { switch ( curr ) { case 0x2E : u->pfx_seg = UD_R_CS; u->pfx_rex = 0; break; case 0x36 : u->pfx_seg = UD_R_SS; u->pfx_rex = 0; break; case 0x3E : u->pfx_seg = UD_R_DS; u->pfx_rex = 0; break; case 0x26 : u->pfx_seg = UD_R_ES; u->pfx_rex = 0; break; case 0x64 : u->pfx_seg = UD_R_FS; u->pfx_rex = 0; break; case 0x65 : u->pfx_seg = UD_R_GS; u->pfx_rex = 0; break; case 0x67 : /* adress-size override prefix */ u->pfx_adr = 0x67; u->pfx_rex = 0; break; case 0xF0 : u->pfx_lock = 0xF0; u->pfx_rex = 0; break; case 0x66: /* the 0x66 sse prefix is only effective if no other sse prefix * has already been specified. */ if ( !u->pfx_insn ) u->pfx_insn = 0x66; u->pfx_opr = 0x66; u->pfx_rex = 0; break; case 0xF2: u->pfx_insn = 0xF2; u->pfx_repne = 0xF2; u->pfx_rex = 0; break; case 0xF3: u->pfx_insn = 0xF3; u->pfx_rep = 0xF3; u->pfx_repe = 0xF3; u->pfx_rex = 0; break; default : /* No more prefixes */ have_pfx = 0; break; } } /* check if we reached max instruction length */ if ( i + 1 == MAX_INSN_LENGTH ) { u->error = 1; break; } } /* return status */ if ( u->error ) return -1; /* rewind back one byte in stream, since the above loop * stops with a non-prefix byte. */ inp_back(u); /* speculatively determine the effective operand mode, * based on the prefixes and the current disassembly * mode. This may be inaccurate, but useful for mode * dependent decoding. */ if ( u->dis_mode == 64 ) { u->opr_mode = REX_W( u->pfx_rex ) ? 64 : ( ( u->pfx_opr ) ? 16 : 32 ) ; u->adr_mode = ( u->pfx_adr ) ? 32 : 64; } else if ( u->dis_mode == 32 ) { u->opr_mode = ( u->pfx_opr ) ? 16 : 32; u->adr_mode = ( u->pfx_adr ) ? 16 : 32; } else if ( u->dis_mode == 16 ) { u->opr_mode = ( u->pfx_opr ) ? 32 : 16; u->adr_mode = ( u->pfx_adr ) ? 32 : 16; } return 0; } /* Searches the instruction tables for the right entry. */ static int search_itab( struct ud * u ) { struct ud_itab_entry * e = NULL; enum ud_itab_index table; uint8_t peek; uint8_t did_peek = 0; uint8_t curr; uint8_t index; /* if in state of error, return */ if ( u->error ) return -1; /* get first byte of opcode. */ inp_next(u); if ( u->error ) return -1; curr = inp_curr(u); /* resolve xchg, nop, pause crazyness */ if ( 0x90 == curr ) { if ( !( u->dis_mode == 64 && REX_B( u->pfx_rex ) ) ) { if ( u->pfx_rep ) { u->pfx_rep = 0; e = & ie_pause; } else { e = & ie_nop; } goto found_entry; } } /* get top-level table */ if ( 0x0F == curr ) { table = ITAB__0F; curr = inp_next(u); if ( u->error ) return -1; /* 2byte opcodes can be modified by 0x66, F3, and F2 prefixes */ if ( 0x66 == u->pfx_insn ) { if ( ud_itab_list[ ITAB__PFX_SSE66__0F ][ curr ].mnemonic != UD_Iinvalid ) { table = ITAB__PFX_SSE66__0F; u->pfx_opr = 0; } } else if ( 0xF2 == u->pfx_insn ) { if ( ud_itab_list[ ITAB__PFX_SSEF2__0F ][ curr ].mnemonic != UD_Iinvalid ) { table = ITAB__PFX_SSEF2__0F; u->pfx_repne = 0; } } else if ( 0xF3 == u->pfx_insn ) { if ( ud_itab_list[ ITAB__PFX_SSEF3__0F ][ curr ].mnemonic != UD_Iinvalid ) { table = ITAB__PFX_SSEF3__0F; u->pfx_repe = 0; u->pfx_rep = 0; } } /* pick an instruction from the 1byte table */ } else { table = ITAB__1BYTE; } index = curr; search: e = & ud_itab_list[ table ][ index ]; /* if mnemonic constant is a standard instruction constant * our search is over. */ if ( e->mnemonic < UD_Id3vil ) { if ( e->mnemonic == UD_Iinvalid ) { if ( did_peek ) { inp_next( u ); if ( u->error ) return -1; } goto found_entry; } goto found_entry; } table = e->prefix; switch ( e->mnemonic ) { case UD_Igrp_reg: peek = inp_peek( u ); did_peek = 1; index = MODRM_REG( peek ); break; case UD_Igrp_mod: peek = inp_peek( u ); did_peek = 1; index = MODRM_MOD( peek ); if ( index == 3 ) index = ITAB__MOD_INDX__11; else index = ITAB__MOD_INDX__NOT_11; break; case UD_Igrp_rm: curr = inp_next( u ); did_peek = 0; if ( u->error ) return -1; index = MODRM_RM( curr ); break; case UD_Igrp_x87: curr = inp_next( u ); did_peek = 0; if ( u->error ) return -1; index = curr - 0xC0; break; case UD_Igrp_3byte: curr = inp_next( u ); did_peek = 0; if (u->error) return -1; index = curr; break; case UD_Igrp_osize: if ( u->opr_mode == 64 ) index = ITAB__MODE_INDX__64; else if ( u->opr_mode == 32 ) index = ITAB__MODE_INDX__32; else index = ITAB__MODE_INDX__16; break; case UD_Igrp_asize: if ( u->adr_mode == 64 ) index = ITAB__MODE_INDX__64; else if ( u->adr_mode == 32 ) index = ITAB__MODE_INDX__32; else index = ITAB__MODE_INDX__16; break; case UD_Igrp_mode: if ( u->dis_mode == 64 ) index = ITAB__MODE_INDX__64; else if ( u->dis_mode == 32 ) index = ITAB__MODE_INDX__32; else index = ITAB__MODE_INDX__16; break; case UD_Igrp_vendor: if ( u->vendor == UD_VENDOR_INTEL ) index = ITAB__VENDOR_INDX__INTEL; else if ( u->vendor == UD_VENDOR_AMD ) index = ITAB__VENDOR_INDX__AMD; else if ( u->vendor == UD_VENDOR_ANY ) index = ITAB__VENDOR_INDX__ANY; else return -1; break; case UD_Id3vil: return -1; break; default: return -1; break; } goto search; found_entry: u->itab_entry = e; u->mnemonic = u->itab_entry->mnemonic; return 0; } static unsigned int resolve_operand_size( const struct ud * u, unsigned int s ) { switch ( s ) { case SZ_V: return ( u->opr_mode ); case SZ_Z: return ( u->opr_mode == 16 ) ? 16 : 32; case SZ_P: return ( u->opr_mode == 16 ) ? SZ_WP : SZ_DP; case SZ_MDQ: return ( u->opr_mode == 16 ) ? 32 : u->opr_mode; case SZ_RDQ: return ( u->dis_mode == 64 ) ? 64 : 32; default: return s; } } static int resolve_mnemonic( struct ud* u ) { /* far/near flags */ u->br_far = 0; u->br_near = 0; /* readjust operand sizes for call/jmp instrcutions */ if ( u->mnemonic == UD_Icall || u->mnemonic == UD_Ijmp ) { /* WP: 16bit pointer */ if ( u->operand[ 0 ].size == SZ_WP ) { u->operand[ 0 ].size = 16; u->br_far = 1; u->br_near= 0; /* DP: 32bit pointer */ } else if ( u->operand[ 0 ].size == SZ_DP ) { u->operand[ 0 ].size = 32; u->br_far = 1; u->br_near= 0; } else { u->br_far = 0; u->br_near= 1; } /* resolve 3dnow weirdness. */ } else if ( u->mnemonic == UD_I3dnow ) { u->mnemonic = ud_itab_list[ ITAB__3DNOW ][ inp_curr( u ) ].mnemonic; } /* SWAPGS is only valid in 64bits mode */ if ( u->mnemonic == UD_Iswapgs && u->dis_mode != 64 ) { u->error = 1; return -1; } return 0; } /* ----------------------------------------------------------------------------- * decode_a()- Decodes operands of the type seg:offset * ----------------------------------------------------------------------------- */ static void decode_a(struct ud* u, struct ud_operand *op) { if (u->opr_mode == 16) { /* seg16:off16 */ op->type = UD_OP_PTR; op->size = 32; op->lval.ptr.off = inp_uint16(u); op->lval.ptr.seg = inp_uint16(u); } else { /* seg16:off32 */ op->type = UD_OP_PTR; op->size = 48; op->lval.ptr.off = inp_uint32(u); op->lval.ptr.seg = inp_uint16(u); } } /* ----------------------------------------------------------------------------- * decode_gpr() - Returns decoded General Purpose Register * ----------------------------------------------------------------------------- */ static enum ud_type decode_gpr(register struct ud* u, unsigned int s, unsigned char rm) { s = resolve_operand_size(u, s); switch (s) { case 64: return UD_R_RAX + rm; case SZ_DP: case 32: return UD_R_EAX + rm; case SZ_WP: case 16: return UD_R_AX + rm; case 8: if (u->dis_mode == 64 && u->pfx_rex) { if (rm >= 4) return UD_R_SPL + (rm-4); return UD_R_AL + rm; } else return UD_R_AL + rm; default: return 0; } } /* ----------------------------------------------------------------------------- * resolve_gpr64() - 64bit General Purpose Register-Selection. * ----------------------------------------------------------------------------- */ static enum ud_type resolve_gpr64(struct ud* u, enum ud_operand_code gpr_op) { if (gpr_op >= OP_rAXr8 && gpr_op <= OP_rDIr15) gpr_op = (gpr_op - OP_rAXr8) | (REX_B(u->pfx_rex) << 3); else gpr_op = (gpr_op - OP_rAX); if (u->opr_mode == 16) return gpr_op + UD_R_AX; if (u->dis_mode == 32 || (u->opr_mode == 32 && ! (REX_W(u->pfx_rex) || u->default64))) { return gpr_op + UD_R_EAX; } return gpr_op + UD_R_RAX; } /* ----------------------------------------------------------------------------- * resolve_gpr32 () - 32bit General Purpose Register-Selection. * ----------------------------------------------------------------------------- */ static enum ud_type resolve_gpr32(struct ud* u, enum ud_operand_code gpr_op) { gpr_op = gpr_op - OP_eAX; if (u->opr_mode == 16) return gpr_op + UD_R_AX; return gpr_op + UD_R_EAX; } /* ----------------------------------------------------------------------------- * resolve_reg() - Resolves the register type * ----------------------------------------------------------------------------- */ static enum ud_type resolve_reg(struct ud* u, unsigned int type, unsigned char i) { switch (type) { case T_MMX : return UD_R_MM0 + (i & 7); case T_XMM : return UD_R_XMM0 + i; case T_CRG : return UD_R_CR0 + i; case T_DBG : return UD_R_DR0 + i; case T_SEG : return UD_R_ES + (i & 7); case T_NONE: default: return UD_NONE; } } /* ----------------------------------------------------------------------------- * decode_imm() - Decodes Immediate values. * ----------------------------------------------------------------------------- */ static void decode_imm(struct ud* u, unsigned int s, struct ud_operand *op) { op->size = resolve_operand_size(u, s); op->type = UD_OP_IMM; switch (op->size) { case 8: op->lval.sbyte = inp_uint8(u); break; case 16: op->lval.uword = inp_uint16(u); break; case 32: op->lval.udword = inp_uint32(u); break; case 64: op->lval.uqword = inp_uint64(u); break; default: return; } } /* ----------------------------------------------------------------------------- * decode_modrm() - Decodes ModRM Byte * ----------------------------------------------------------------------------- */ static void decode_modrm(struct ud* u, struct ud_operand *op, unsigned int s, unsigned char rm_type, struct ud_operand *opreg, unsigned char reg_size, unsigned char reg_type) { unsigned char mod, rm, reg; inp_next(u); /* get mod, r/m and reg fields */ mod = MODRM_MOD(inp_curr(u)); rm = (REX_B(u->pfx_rex) << 3) | MODRM_RM(inp_curr(u)); reg = (REX_R(u->pfx_rex) << 3) | MODRM_REG(inp_curr(u)); op->size = resolve_operand_size(u, s); /* if mod is 11b, then the UD_R_m specifies a gpr/mmx/sse/control/debug */ if (mod == 3) { op->type = UD_OP_REG; if (rm_type == T_GPR) op->base = decode_gpr(u, op->size, rm); else op->base = resolve_reg(u, rm_type, (REX_B(u->pfx_rex) << 3) | (rm&7)); } /* else its memory addressing */ else { op->type = UD_OP_MEM; /* 64bit addressing */ if (u->adr_mode == 64) { op->base = UD_R_RAX + rm; /* get offset type */ if (mod == 1) op->offset = 8; else if (mod == 2) op->offset = 32; else if (mod == 0 && (rm & 7) == 5) { op->base = UD_R_RIP; op->offset = 32; } else op->offset = 0; /* Scale-Index-Base (SIB) */ if ((rm & 7) == 4) { inp_next(u); op->scale = (1 << SIB_S(inp_curr(u))) & ~1; op->index = UD_R_RAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3)); op->base = UD_R_RAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3)); /* special conditions for base reference */ if (op->index == UD_R_RSP) { op->index = UD_NONE; op->scale = UD_NONE; } if (op->base == UD_R_RBP || op->base == UD_R_R13) { if (mod == 0) op->base = UD_NONE; if (mod == 1) op->offset = 8; else op->offset = 32; } } } /* 32-Bit addressing mode */ else if (u->adr_mode == 32) { /* get base */ op->base = UD_R_EAX + rm; /* get offset type */ if (mod == 1) op->offset = 8; else if (mod == 2) op->offset = 32; else if (mod == 0 && rm == 5) { op->base = UD_NONE; op->offset = 32; } else op->offset = 0; /* Scale-Index-Base (SIB) */ if ((rm & 7) == 4) { inp_next(u); op->scale = (1 << SIB_S(inp_curr(u))) & ~1; op->index = UD_R_EAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3)); op->base = UD_R_EAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3)); if (op->index == UD_R_ESP) { op->index = UD_NONE; op->scale = UD_NONE; } /* special condition for base reference */ if (op->base == UD_R_EBP) { if (mod == 0) op->base = UD_NONE; if (mod == 1) op->offset = 8; else op->offset = 32; } } } /* 16bit addressing mode */ else { switch (rm) { case 0: op->base = UD_R_BX; op->index = UD_R_SI; break; case 1: op->base = UD_R_BX; op->index = UD_R_DI; break; case 2: op->base = UD_R_BP; op->index = UD_R_SI; break; case 3: op->base = UD_R_BP; op->index = UD_R_DI; break; case 4: op->base = UD_R_SI; break; case 5: op->base = UD_R_DI; break; case 6: op->base = UD_R_BP; break; case 7: op->base = UD_R_BX; break; } if (mod == 0 && rm == 6) { op->offset= 16; op->base = UD_NONE; } else if (mod == 1) op->offset = 8; else if (mod == 2) op->offset = 16; } } /* extract offset, if any */ switch(op->offset) { case 8 : op->lval.ubyte = inp_uint8(u); break; case 16: op->lval.uword = inp_uint16(u); break; case 32: op->lval.udword = inp_uint32(u); break; case 64: op->lval.uqword = inp_uint64(u); break; default: break; } /* resolve register encoded in reg field */ if (opreg) { opreg->type = UD_OP_REG; opreg->size = resolve_operand_size(u, reg_size); if (reg_type == T_GPR) opreg->base = decode_gpr(u, opreg->size, reg); else opreg->base = resolve_reg(u, reg_type, reg); } } /* ----------------------------------------------------------------------------- * decode_o() - Decodes offset * ----------------------------------------------------------------------------- */ static void decode_o(struct ud* u, unsigned int s, struct ud_operand *op) { switch (u->adr_mode) { case 64: op->offset = 64; op->lval.uqword = inp_uint64(u); break; case 32: op->offset = 32; op->lval.udword = inp_uint32(u); break; case 16: op->offset = 16; op->lval.uword = inp_uint16(u); break; default: return; } op->type = UD_OP_MEM; op->size = resolve_operand_size(u, s); } /* ----------------------------------------------------------------------------- * disasm_operands() - Disassembles Operands. * ----------------------------------------------------------------------------- */ static int disasm_operands(register struct ud* u) { /* mopXt = map entry, operand X, type; */ enum ud_operand_code mop1t = u->itab_entry->operand1.type; enum ud_operand_code mop2t = u->itab_entry->operand2.type; enum ud_operand_code mop3t = u->itab_entry->operand3.type; /* mopXs = map entry, operand X, size */ unsigned int mop1s = u->itab_entry->operand1.size; unsigned int mop2s = u->itab_entry->operand2.size; unsigned int mop3s = u->itab_entry->operand3.size; /* iop = instruction operand */ register struct ud_operand* iop = u->operand; switch(mop1t) { case OP_A : decode_a(u, &(iop[0])); break; /* M[b] ... */ case OP_M : if (MODRM_MOD(inp_peek(u)) == 3) u->error= 1; /* E, G/P/V/I/CL/1/S */ case OP_E : if (mop2t == OP_G) { decode_modrm(u, &(iop[0]), mop1s, T_GPR, &(iop[1]), mop2s, T_GPR); if (mop3t == OP_I) decode_imm(u, mop3s, &(iop[2])); else if (mop3t == OP_CL) { iop[2].type = UD_OP_REG; iop[2].base = UD_R_CL; iop[2].size = 8; } } else if (mop2t == OP_P) decode_modrm(u, &(iop[0]), mop1s, T_GPR, &(iop[1]), mop2s, T_MMX); else if (mop2t == OP_V) decode_modrm(u, &(iop[0]), mop1s, T_GPR, &(iop[1]), mop2s, T_XMM); else if (mop2t == OP_S) decode_modrm(u, &(iop[0]), mop1s, T_GPR, &(iop[1]), mop2s, T_SEG); else { decode_modrm(u, &(iop[0]), mop1s, T_GPR, NULL, 0, T_NONE); if (mop2t == OP_CL) { iop[1].type = UD_OP_REG; iop[1].base = UD_R_CL; iop[1].size = 8; } else if (mop2t == OP_I1) { iop[1].type = UD_OP_CONST; u->operand[1].lval.udword = 1; } else if (mop2t == OP_I) { decode_imm(u, mop2s, &(iop[1])); } } break; /* G, E/PR[,I]/VR */ case OP_G : if (mop2t == OP_M) { if (MODRM_MOD(inp_peek(u)) == 3) u->error= 1; decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_GPR); } else if (mop2t == OP_E) { decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_GPR); if (mop3t == OP_I) decode_imm(u, mop3s, &(iop[2])); } else if (mop2t == OP_PR) { decode_modrm(u, &(iop[1]), mop2s, T_MMX, &(iop[0]), mop1s, T_GPR); if (mop3t == OP_I) decode_imm(u, mop3s, &(iop[2])); } else if (mop2t == OP_VR) { if (MODRM_MOD(inp_peek(u)) != 3) u->error = 1; decode_modrm(u, &(iop[1]), mop2s, T_XMM, &(iop[0]), mop1s, T_GPR); } else if (mop2t == OP_W) decode_modrm(u, &(iop[1]), mop2s, T_XMM, &(iop[0]), mop1s, T_GPR); break; /* AL..BH, I/O/DX */ case OP_AL : case OP_CL : case OP_DL : case OP_BL : case OP_AH : case OP_CH : case OP_DH : case OP_BH : iop[0].type = UD_OP_REG; iop[0].base = UD_R_AL + (mop1t - OP_AL); iop[0].size = 8; if (mop2t == OP_I) decode_imm(u, mop2s, &(iop[1])); else if (mop2t == OP_DX) { iop[1].type = UD_OP_REG; iop[1].base = UD_R_DX; iop[1].size = 16; } else if (mop2t == OP_O) decode_o(u, mop2s, &(iop[1])); break; /* rAX[r8]..rDI[r15], I/rAX..rDI/O */ case OP_rAXr8 : case OP_rCXr9 : case OP_rDXr10 : case OP_rBXr11 : case OP_rSPr12: case OP_rBPr13: case OP_rSIr14 : case OP_rDIr15 : case OP_rAX : case OP_rCX : case OP_rDX : case OP_rBX : case OP_rSP : case OP_rBP : case OP_rSI : case OP_rDI : iop[0].type = UD_OP_REG; iop[0].base = resolve_gpr64(u, mop1t); if (mop2t == OP_I) decode_imm(u, mop2s, &(iop[1])); else if (mop2t >= OP_rAX && mop2t <= OP_rDI) { iop[1].type = UD_OP_REG; iop[1].base = resolve_gpr64(u, mop2t); } else if (mop2t == OP_O) { decode_o(u, mop2s, &(iop[1])); iop[0].size = resolve_operand_size(u, mop2s); } break; /* AL[r8b]..BH[r15b], I */ case OP_ALr8b : case OP_CLr9b : case OP_DLr10b : case OP_BLr11b : case OP_AHr12b: case OP_CHr13b: case OP_DHr14b : case OP_BHr15b : { ud_type_t gpr = (mop1t - OP_ALr8b) + UD_R_AL + (REX_B(u->pfx_rex) << 3); if (UD_R_AH <= gpr && u->pfx_rex) gpr = gpr + 4; iop[0].type = UD_OP_REG; iop[0].base = gpr; if (mop2t == OP_I) decode_imm(u, mop2s, &(iop[1])); break; } /* eAX..eDX, DX/I */ case OP_eAX : case OP_eCX : case OP_eDX : case OP_eBX : case OP_eSP : case OP_eBP : case OP_eSI : case OP_eDI : iop[0].type = UD_OP_REG; iop[0].base = resolve_gpr32(u, mop1t); if (mop2t == OP_DX) { iop[1].type = UD_OP_REG; iop[1].base = UD_R_DX; iop[1].size = 16; } else if (mop2t == OP_I) decode_imm(u, mop2s, &(iop[1])); break; /* ES..GS */ case OP_ES : case OP_CS : case OP_DS : case OP_SS : case OP_FS : case OP_GS : /* in 64bits mode, only fs and gs are allowed */ if (u->dis_mode == 64) if (mop1t != OP_FS && mop1t != OP_GS) u->error= 1; iop[0].type = UD_OP_REG; iop[0].base = (mop1t - OP_ES) + UD_R_ES; iop[0].size = 16; break; /* J */ case OP_J : decode_imm(u, mop1s, &(iop[0])); iop[0].type = UD_OP_JIMM; break ; /* PR, I */ case OP_PR: if (MODRM_MOD(inp_peek(u)) != 3) u->error = 1; decode_modrm(u, &(iop[0]), mop1s, T_MMX, NULL, 0, T_NONE); if (mop2t == OP_I) decode_imm(u, mop2s, &(iop[1])); break; /* VR, I */ case OP_VR: if (MODRM_MOD(inp_peek(u)) != 3) u->error = 1; decode_modrm(u, &(iop[0]), mop1s, T_XMM, NULL, 0, T_NONE); if (mop2t == OP_I) decode_imm(u, mop2s, &(iop[1])); break; /* P, Q[,I]/W/E[,I],VR */ case OP_P : if (mop2t == OP_Q) { decode_modrm(u, &(iop[1]), mop2s, T_MMX, &(iop[0]), mop1s, T_MMX); if (mop3t == OP_I) decode_imm(u, mop3s, &(iop[2])); } else if (mop2t == OP_W) { decode_modrm(u, &(iop[1]), mop2s, T_XMM, &(iop[0]), mop1s, T_MMX); } else if (mop2t == OP_VR) { if (MODRM_MOD(inp_peek(u)) != 3) u->error = 1; decode_modrm(u, &(iop[1]), mop2s, T_XMM, &(iop[0]), mop1s, T_MMX); } else if (mop2t == OP_E) { decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_MMX); if (mop3t == OP_I) decode_imm(u, mop3s, &(iop[2])); } break; /* R, C/D */ case OP_R : if (mop2t == OP_C) decode_modrm(u, &(iop[0]), mop1s, T_GPR, &(iop[1]), mop2s, T_CRG); else if (mop2t == OP_D) decode_modrm(u, &(iop[0]), mop1s, T_GPR, &(iop[1]), mop2s, T_DBG); break; /* C, R */ case OP_C : decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_CRG); break; /* D, R */ case OP_D : decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_DBG); break; /* Q, P */ case OP_Q : decode_modrm(u, &(iop[0]), mop1s, T_MMX, &(iop[1]), mop2s, T_MMX); break; /* S, E */ case OP_S : decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_SEG); break; /* W, V */ case OP_W : decode_modrm(u, &(iop[0]), mop1s, T_XMM, &(iop[1]), mop2s, T_XMM); break; /* V, W[,I]/Q/M/E */ case OP_V : if (mop2t == OP_W) { /* special cases for movlps and movhps */ if (MODRM_MOD(inp_peek(u)) == 3) { if (u->mnemonic == UD_Imovlps) u->mnemonic = UD_Imovhlps; else if (u->mnemonic == UD_Imovhps) u->mnemonic = UD_Imovlhps; } decode_modrm(u, &(iop[1]), mop2s, T_XMM, &(iop[0]), mop1s, T_XMM); if (mop3t == OP_I) decode_imm(u, mop3s, &(iop[2])); } else if (mop2t == OP_Q) decode_modrm(u, &(iop[1]), mop2s, T_MMX, &(iop[0]), mop1s, T_XMM); else if (mop2t == OP_M) { if (MODRM_MOD(inp_peek(u)) == 3) u->error= 1; decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_XMM); } else if (mop2t == OP_E) { decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_XMM); } else if (mop2t == OP_PR) { decode_modrm(u, &(iop[1]), mop2s, T_MMX, &(iop[0]), mop1s, T_XMM); } break; /* DX, eAX/AL */ case OP_DX : iop[0].type = UD_OP_REG; iop[0].base = UD_R_DX; iop[0].size = 16; if (mop2t == OP_eAX) { iop[1].type = UD_OP_REG; iop[1].base = resolve_gpr32(u, mop2t); } else if (mop2t == OP_AL) { iop[1].type = UD_OP_REG; iop[1].base = UD_R_AL; iop[1].size = 8; } break; /* I, I/AL/eAX */ case OP_I : decode_imm(u, mop1s, &(iop[0])); if (mop2t == OP_I) decode_imm(u, mop2s, &(iop[1])); else if (mop2t == OP_AL) { iop[1].type = UD_OP_REG; iop[1].base = UD_R_AL; iop[1].size = 16; } else if (mop2t == OP_eAX) { iop[1].type = UD_OP_REG; iop[1].base = resolve_gpr32(u, mop2t); } break; /* O, AL/eAX */ case OP_O : decode_o(u, mop1s, &(iop[0])); iop[1].type = UD_OP_REG; iop[1].size = resolve_operand_size(u, mop1s); if (mop2t == OP_AL) iop[1].base = UD_R_AL; else if (mop2t == OP_eAX) iop[1].base = resolve_gpr32(u, mop2t); else if (mop2t == OP_rAX) iop[1].base = resolve_gpr64(u, mop2t); break; /* 3 */ case OP_I3 : iop[0].type = UD_OP_CONST; iop[0].lval.sbyte = 3; break; /* ST(n), ST(n) */ case OP_ST0 : case OP_ST1 : case OP_ST2 : case OP_ST3 : case OP_ST4 : case OP_ST5 : case OP_ST6 : case OP_ST7 : iop[0].type = UD_OP_REG; iop[0].base = (mop1t-OP_ST0) + UD_R_ST0; iop[0].size = 0; if (mop2t >= OP_ST0 && mop2t <= OP_ST7) { iop[1].type = UD_OP_REG; iop[1].base = (mop2t-OP_ST0) + UD_R_ST0; iop[1].size = 0; } break; /* AX */ case OP_AX: iop[0].type = UD_OP_REG; iop[0].base = UD_R_AX; iop[0].size = 16; break; /* none */ default : iop[0].type = iop[1].type = iop[2].type = UD_NONE; } return 0; } /* ----------------------------------------------------------------------------- * clear_insn() - clear instruction pointer * ----------------------------------------------------------------------------- */ static int clear_insn(register struct ud* u) { u->error = 0; u->pfx_seg = 0; u->pfx_opr = 0; u->pfx_adr = 0; u->pfx_lock = 0; u->pfx_repne = 0; u->pfx_rep = 0; u->pfx_repe = 0; u->pfx_seg = 0; u->pfx_rex = 0; u->pfx_insn = 0; u->mnemonic = UD_Inone; u->itab_entry = NULL; memset( &u->operand[ 0 ], 0, sizeof( struct ud_operand ) ); memset( &u->operand[ 1 ], 0, sizeof( struct ud_operand ) ); memset( &u->operand[ 2 ], 0, sizeof( struct ud_operand ) ); return 0; } static int do_mode( struct ud* u ) { /* if in error state, bail out */ if ( u->error ) return -1; /* propagate perfix effects */ if ( u->dis_mode == 64 ) { /* set 64bit-mode flags */ /* Check validity of instruction m64 */ if ( P_INV64( u->itab_entry->prefix ) ) { u->error = 1; return -1; } /* effective rex prefix is the effective mask for the * instruction hard-coded in the opcode map. */ u->pfx_rex = ( u->pfx_rex & 0x40 ) | ( u->pfx_rex & REX_PFX_MASK( u->itab_entry->prefix ) ); /* whether this instruction has a default operand size of * 64bit, also hardcoded into the opcode map. */ u->default64 = P_DEF64( u->itab_entry->prefix ); /* calculate effective operand size */ if ( REX_W( u->pfx_rex ) ) { u->opr_mode = 64; } else if ( u->pfx_opr ) { u->opr_mode = 16; } else { /* unless the default opr size of instruction is 64, * the effective operand size in the absence of rex.w * prefix is 32. */ u->opr_mode = ( u->default64 ) ? 64 : 32; } /* calculate effective address size */ u->adr_mode = (u->pfx_adr) ? 32 : 64; } else if ( u->dis_mode == 32 ) { /* set 32bit-mode flags */ u->opr_mode = ( u->pfx_opr ) ? 16 : 32; u->adr_mode = ( u->pfx_adr ) ? 16 : 32; } else if ( u->dis_mode == 16 ) { /* set 16bit-mode flags */ u->opr_mode = ( u->pfx_opr ) ? 32 : 16; u->adr_mode = ( u->pfx_adr ) ? 32 : 16; } /* These flags determine which operand to apply the operand size * cast to. */ u->c1 = ( P_C1( u->itab_entry->prefix ) ) ? 1 : 0; u->c2 = ( P_C2( u->itab_entry->prefix ) ) ? 1 : 0; u->c3 = ( P_C3( u->itab_entry->prefix ) ) ? 1 : 0; /* set flags for implicit addressing */ u->implicit_addr = P_IMPADDR( u->itab_entry->prefix ); return 0; } static int gen_hex( struct ud *u ) { unsigned int i; unsigned char *src_ptr = inp_sess( u ); char* src_hex; /* bail out if in error stat. */ if ( u->error ) return -1; /* output buffer pointe */ src_hex = ( char* ) u->insn_hexcode; /* for each byte used to decode instruction */ for ( i = 0; i < u->inp_ctr; ++i, ++src_ptr) { sprintf( src_hex, "%02x", *src_ptr & 0xFF ); src_hex += 2; } return 0; } /* ============================================================================= * ud_decode() - Instruction decoder. Returns the number of bytes decoded. * ============================================================================= */ unsigned int ud_decode( struct ud* u ) { inp_start(u); if ( clear_insn( u ) ) { ; /* error */ } else if ( get_prefixes( u ) != 0 ) { ; /* error */ } else if ( search_itab( u ) != 0 ) { ; /* error */ } else if ( do_mode( u ) != 0 ) { ; /* error */ } else if ( disasm_operands( u ) != 0 ) { ; /* error */ } else if ( resolve_mnemonic( u ) != 0 ) { ; /* error */ } /* Handle decode error. */ if ( u->error ) { /* clear out the decode data. */ clear_insn( u ); /* mark the sequence of bytes as invalid. */ u->itab_entry = & ie_invalid; u->mnemonic = u->itab_entry->mnemonic; } u->insn_offset = u->pc; /* set offset of instruction */ u->insn_fill = 0; /* set translation buffer index to 0 */ u->pc += u->inp_ctr; /* move program counter by bytes decoded */ gen_hex( u ); /* generate hex code */ /* return number of bytes disassembled. */ return u->inp_ctr; } /* vim:cindent * vim:ts=4 * vim:sw=4 * vim:expandtab */ ksplice-0.9.9/kmodsrc/x86/libudis86/udis86.c0000644000000000000000000001237111206570615017056 0ustar rootroot/* udis86 - libudis86/udis86.c * * Copyright (c) 2002-2009 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "input.h" #include "extern.h" #ifndef __UD_STANDALONE__ # include # include #endif /* __UD_STANDALONE__ */ /* ============================================================================= * ud_init() - Initializes ud_t object. * ============================================================================= */ extern void ud_init(struct ud* u) { memset((void*)u, 0, sizeof(struct ud)); ud_set_mode(u, 16); u->mnemonic = UD_Iinvalid; ud_set_pc(u, 0); #ifndef __UD_STANDALONE__ ud_set_input_file(u, stdin); #endif /* __UD_STANDALONE__ */ } /* ============================================================================= * ud_disassemble() - disassembles one instruction and returns the number of * bytes disassembled. A zero means end of disassembly. * ============================================================================= */ extern unsigned int ud_disassemble(struct ud* u) { if (ud_input_end(u)) return 0; u->insn_buffer[0] = u->insn_hexcode[0] = 0; if (ud_decode(u) == 0) return 0; if (u->translator) u->translator(u); return ud_insn_len(u); } /* ============================================================================= * ud_set_mode() - Set Disassemly Mode. * ============================================================================= */ extern void ud_set_mode(struct ud* u, uint8_t m) { switch(m) { case 16: case 32: case 64: u->dis_mode = m ; return; default: u->dis_mode = 16; return; } } /* ============================================================================= * ud_set_vendor() - Set vendor. * ============================================================================= */ extern void ud_set_vendor(struct ud* u, unsigned v) { switch(v) { case UD_VENDOR_INTEL: u->vendor = v; break; case UD_VENDOR_ANY: u->vendor = v; break; default: u->vendor = UD_VENDOR_AMD; } } /* ============================================================================= * ud_set_pc() - Sets code origin. * ============================================================================= */ extern void ud_set_pc(struct ud* u, uint64_t o) { u->pc = o; } /* ============================================================================= * ud_set_syntax() - Sets the output syntax. * ============================================================================= */ extern void ud_set_syntax(struct ud* u, void (*t)(struct ud*)) { u->translator = t; } /* ============================================================================= * ud_insn() - returns the disassembled instruction * ============================================================================= */ extern char* ud_insn_asm(struct ud* u) { return u->insn_buffer; } /* ============================================================================= * ud_insn_offset() - Returns the offset. * ============================================================================= */ extern uint64_t ud_insn_off(struct ud* u) { return u->insn_offset; } /* ============================================================================= * ud_insn_hex() - Returns hex form of disassembled instruction. * ============================================================================= */ extern char* ud_insn_hex(struct ud* u) { return u->insn_hexcode; } /* ============================================================================= * ud_insn_ptr() - Returns code disassembled. * ============================================================================= */ extern uint8_t* ud_insn_ptr(struct ud* u) { return u->inp_sess; } /* ============================================================================= * ud_insn_len() - Returns the count of bytes disassembled. * ============================================================================= */ extern unsigned int ud_insn_len(struct ud* u) { return u->inp_ctr; } ksplice-0.9.9/kmodsrc/x86/libudis86/input.h0000644000000000000000000000461511206570615017102 0ustar rootroot/* udis86 - libudis86/input.h * * Copyright (c) 2002-2009 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef UD_INPUT_H #define UD_INPUT_H #include "types.h" uint8_t inp_next(struct ud*); uint8_t inp_peek(struct ud*); uint8_t inp_uint8(struct ud*); uint16_t inp_uint16(struct ud*); uint32_t inp_uint32(struct ud*); uint64_t inp_uint64(struct ud*); void inp_move(struct ud*, size_t); void inp_back(struct ud*); /* inp_init() - Initializes the input system. */ #define inp_init(u) \ do { \ u->inp_curr = 0; \ u->inp_fill = 0; \ u->inp_ctr = 0; \ u->inp_end = 0; \ } while (0) /* inp_start() - Should be called before each de-code operation. */ #define inp_start(u) u->inp_ctr = 0 /* inp_back() - Resets the current pointer to its position before the current * instruction disassembly was started. */ #define inp_reset(u) \ do { \ u->inp_curr -= u->inp_ctr; \ u->inp_ctr = 0; \ } while (0) /* inp_sess() - Returns the pointer to current session. */ #define inp_sess(u) (u->inp_sess) /* inp_cur() - Returns the current input byte. */ #define inp_curr(u) ((u)->inp_cache[(u)->inp_curr]) #endif ksplice-0.9.9/kmodsrc/x86/libudis86/.gitignore0000644000000000000000000000002011243613223017536 0ustar rootroot/itab.c /itab.h ksplice-0.9.9/kmodsrc/x86/libudis86/extern.h0000644000000000000000000000546011206570615017247 0ustar rootroot/* udis86 - libudis86/extern.h * * Copyright (c) 2002-2009 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef UD_EXTERN_H #define UD_EXTERN_H #ifdef __cplusplus extern "C" { #endif #include "types.h" /* ============================= PUBLIC API ================================= */ extern void ud_init(struct ud*); extern void ud_set_mode(struct ud*, uint8_t); extern void ud_set_pc(struct ud*, uint64_t); extern void ud_set_input_hook(struct ud*, int (*)(struct ud*)); extern void ud_set_input_buffer(struct ud*, uint8_t*, size_t); #ifndef __UD_STANDALONE__ extern void ud_set_input_file(struct ud*, FILE*); #endif /* __UD_STANDALONE__ */ extern void ud_set_vendor(struct ud*, unsigned); extern void ud_set_syntax(struct ud*, void (*)(struct ud*)); extern void ud_input_skip(struct ud*, size_t); extern int ud_input_end(struct ud*); extern unsigned int ud_decode(struct ud*); extern unsigned int ud_disassemble(struct ud*); extern void ud_translate_intel(struct ud*); extern void ud_translate_att(struct ud*); extern char* ud_insn_asm(struct ud* u); extern uint8_t* ud_insn_ptr(struct ud* u); extern uint64_t ud_insn_off(struct ud*); extern char* ud_insn_hex(struct ud*); extern unsigned int ud_insn_len(struct ud* u); extern const char* ud_lookup_mnemonic(enum ud_mnemonic_code c); extern void ud_set_user_opaque_data(struct ud*, void*); extern void *ud_get_user_opaque_data(struct ud*); /* ========================================================================== */ #ifdef __cplusplus } #endif #endif ksplice-0.9.9/kmodsrc/x86/libudis86/itab.c0000644000000000000000000073666011244274432016671 0ustar rootroot /* itab.c -- auto generated by opgen.py, do not edit. */ #include "types.h" #include "decode.h" #include "itab.h" const char * ud_mnemonics_str[] = { "3dnow", "aaa", "aad", "aam", "aas", "adc", "add", "addpd", "addps", "addsd", "addss", "addsubpd", "addsubps", "and", "andpd", "andps", "andnpd", "andnps", "arpl", "movsxd", "bound", "bsf", "bsr", "bswap", "bt", "btc", "btr", "bts", "call", "cbw", "cwde", "cdqe", "clc", "cld", "clflush", "clgi", "cli", "clts", "cmc", "cmovo", "cmovno", "cmovb", "cmovae", "cmovz", "cmovnz", "cmovbe", "cmova", "cmovs", "cmovns", "cmovp", "cmovnp", "cmovl", "cmovge", "cmovle", "cmovg", "cmp", "cmppd", "cmpps", "cmpsb", "cmpsw", "cmpsd", "cmpsq", "cmpss", "cmpxchg", "cmpxchg8b", "comisd", "comiss", "cpuid", "cvtdq2pd", "cvtdq2ps", "cvtpd2dq", "cvtpd2pi", "cvtpd2ps", "cvtpi2ps", "cvtpi2pd", "cvtps2dq", "cvtps2pi", "cvtps2pd", "cvtsd2si", "cvtsd2ss", "cvtsi2ss", "cvtss2si", "cvtss2sd", "cvttpd2pi", "cvttpd2dq", "cvttps2dq", "cvttps2pi", "cvttsd2si", "cvtsi2sd", "cvttss2si", "cwd", "cdq", "cqo", "daa", "das", "dec", "div", "divpd", "divps", "divsd", "divss", "emms", "enter", "f2xm1", "fabs", "fadd", "faddp", "fbld", "fbstp", "fchs", "fclex", "fcmovb", "fcmove", "fcmovbe", "fcmovu", "fcmovnb", "fcmovne", "fcmovnbe", "fcmovnu", "fucomi", "fcom", "fcom2", "fcomp3", "fcomi", "fucomip", "fcomip", "fcomp", "fcomp5", "fcompp", "fcos", "fdecstp", "fdiv", "fdivp", "fdivr", "fdivrp", "femms", "ffree", "ffreep", "ficom", "ficomp", "fild", "fncstp", "fninit", "fiadd", "fidivr", "fidiv", "fisub", "fisubr", "fist", "fistp", "fisttp", "fld", "fld1", "fldl2t", "fldl2e", "fldlpi", "fldlg2", "fldln2", "fldz", "fldcw", "fldenv", "fmul", "fmulp", "fimul", "fnop", "fpatan", "fprem", "fprem1", "fptan", "frndint", "frstor", "fnsave", "fscale", "fsin", "fsincos", "fsqrt", "fstp", "fstp1", "fstp8", "fstp9", "fst", "fnstcw", "fnstenv", "fnstsw", "fsub", "fsubp", "fsubr", "fsubrp", "ftst", "fucom", "fucomp", "fucompp", "fxam", "fxch", "fxch4", "fxch7", "fxrstor", "fxsave", "fpxtract", "fyl2x", "fyl2xp1", "haddpd", "haddps", "hlt", "hsubpd", "hsubps", "idiv", "in", "imul", "inc", "insb", "insw", "insd", "int1", "int3", "int", "into", "invd", "invept", "invlpg", "invlpga", "invvpid", "iretw", "iretd", "iretq", "jo", "jno", "jb", "jae", "jz", "jnz", "jbe", "ja", "js", "jns", "jp", "jnp", "jl", "jge", "jle", "jg", "jcxz", "jecxz", "jrcxz", "jmp", "lahf", "lar", "lddqu", "ldmxcsr", "lds", "lea", "les", "lfs", "lgs", "lidt", "lss", "leave", "lfence", "lgdt", "lldt", "lmsw", "lock", "lodsb", "lodsw", "lodsd", "lodsq", "loopnz", "loope", "loop", "lsl", "ltr", "maskmovq", "maxpd", "maxps", "maxsd", "maxss", "mfence", "minpd", "minps", "minsd", "minss", "monitor", "montmul", "mov", "movapd", "movaps", "movd", "movddup", "movdqa", "movdqu", "movdq2q", "movhpd", "movhps", "movlhps", "movlpd", "movlps", "movhlps", "movmskpd", "movmskps", "movntdq", "movnti", "movntpd", "movntps", "movntq", "movq", "movqa", "movq2dq", "movsb", "movsw", "movsd", "movsq", "movsldup", "movshdup", "movss", "movsx", "movupd", "movups", "movzx", "mul", "mulpd", "mulps", "mulsd", "mulss", "mwait", "neg", "nop", "not", "or", "orpd", "orps", "out", "outsb", "outsw", "outsd", "outsq", "packsswb", "packssdw", "packuswb", "paddb", "paddw", "paddq", "paddsb", "paddsw", "paddusb", "paddusw", "pand", "pandn", "pause", "pavgb", "pavgw", "pcmpeqb", "pcmpeqw", "pcmpeqd", "pcmpgtb", "pcmpgtw", "pcmpgtd", "pextrw", "pinsrw", "pmaddwd", "pmaxsw", "pmaxub", "pminsw", "pminub", "pmovmskb", "pmulhuw", "pmulhw", "pmullw", "pmuludq", "pop", "popa", "popad", "popfw", "popfd", "popfq", "por", "prefetch", "prefetchnta", "prefetcht0", "prefetcht1", "prefetcht2", "psadbw", "pshufd", "pshufhw", "pshuflw", "pshufw", "pslldq", "psllw", "pslld", "psllq", "psraw", "psrad", "psrlw", "psrld", "psrlq", "psrldq", "psubb", "psubw", "psubd", "psubq", "psubsb", "psubsw", "psubusb", "psubusw", "punpckhbw", "punpckhwd", "punpckhdq", "punpckhqdq", "punpcklbw", "punpcklwd", "punpckldq", "punpcklqdq", "pi2fw", "pi2fd", "pf2iw", "pf2id", "pfnacc", "pfpnacc", "pfcmpge", "pfmin", "pfrcp", "pfrsqrt", "pfsub", "pfadd", "pfcmpgt", "pfmax", "pfrcpit1", "pfrspit1", "pfsubr", "pfacc", "pfcmpeq", "pfmul", "pfrcpit2", "pmulhrw", "pswapd", "pavgusb", "push", "pusha", "pushad", "pushfw", "pushfd", "pushfq", "pxor", "rcl", "rcr", "rol", "ror", "rcpps", "rcpss", "rdmsr", "rdpmc", "rdtsc", "rdtscp", "repne", "rep", "ret", "retf", "rsm", "rsqrtps", "rsqrtss", "sahf", "sal", "salc", "sar", "shl", "shr", "sbb", "scasb", "scasw", "scasd", "scasq", "seto", "setno", "setb", "setnb", "setz", "setnz", "setbe", "seta", "sets", "setns", "setp", "setnp", "setl", "setge", "setle", "setg", "sfence", "sgdt", "shld", "shrd", "shufpd", "shufps", "sidt", "sldt", "smsw", "sqrtps", "sqrtpd", "sqrtsd", "sqrtss", "stc", "std", "stgi", "sti", "skinit", "stmxcsr", "stosb", "stosw", "stosd", "stosq", "str", "sub", "subpd", "subps", "subsd", "subss", "swapgs", "syscall", "sysenter", "sysexit", "sysret", "test", "ucomisd", "ucomiss", "ud2", "unpckhpd", "unpckhps", "unpcklps", "unpcklpd", "verr", "verw", "vmcall", "vmclear", "vmxon", "vmptrld", "vmptrst", "vmlaunch", "vmresume", "vmxoff", "vmread", "vmwrite", "vmrun", "vmmcall", "vmload", "vmsave", "wait", "wbinvd", "wrmsr", "xadd", "xchg", "xlatb", "xor", "xorpd", "xorps", "xcryptecb", "xcryptcbc", "xcryptctr", "xcryptcfb", "xcryptofb", "xgetbv", "xrstor", "xsetbv", "xsave", "xsha1", "xsha256", "xstore", "db", "invalid", }; static struct ud_itab_entry itab__0f[256] = { /* 00 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_00__REG }, /* 01 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG }, /* 02 */ { UD_Ilar, O_Gv, O_Ew, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Ilsl, O_Gv, O_Ew, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Isyscall, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Iclts, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Isysret, O_NONE, O_NONE, O_NONE, P_none }, /* 08 */ { UD_Iinvd, O_NONE, O_NONE, O_NONE, P_none }, /* 09 */ { UD_Iwbinvd, O_NONE, O_NONE, O_NONE, P_none }, /* 0A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0B */ { UD_Iud2, O_NONE, O_NONE, O_NONE, P_none }, /* 0C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0D */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_0D__REG }, /* 0E */ { UD_Ifemms, O_NONE, O_NONE, O_NONE, P_none }, /* 0F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 10 */ { UD_Imovups, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 11 */ { UD_Imovups, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 12 */ { UD_Imovlps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 13 */ { UD_Imovlps, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 14 */ { UD_Iunpcklps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 15 */ { UD_Iunpckhps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 16 */ { UD_Imovhps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 17 */ { UD_Imovhps, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 18 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_18__REG }, /* 19 */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1A */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1B */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1C */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1D */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1E */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1F */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 20 */ { UD_Imov, O_R, O_C, O_NONE, P_rexr }, /* 21 */ { UD_Imov, O_R, O_D, O_NONE, P_rexr }, /* 22 */ { UD_Imov, O_C, O_R, O_NONE, P_rexr }, /* 23 */ { UD_Imov, O_D, O_R, O_NONE, P_rexr }, /* 24 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 25 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 26 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 27 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 28 */ { UD_Imovaps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 29 */ { UD_Imovaps, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 2A */ { UD_Icvtpi2ps, O_V, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 2B */ { UD_Imovntps, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 2C */ { UD_Icvttps2pi, O_P, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 2D */ { UD_Icvtps2pi, O_P, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 2E */ { UD_Iucomiss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 2F */ { UD_Icomiss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 30 */ { UD_Iwrmsr, O_NONE, O_NONE, O_NONE, P_none }, /* 31 */ { UD_Irdtsc, O_NONE, O_NONE, O_NONE, P_none }, /* 32 */ { UD_Irdmsr, O_NONE, O_NONE, O_NONE, P_none }, /* 33 */ { UD_Irdpmc, O_NONE, O_NONE, O_NONE, P_none }, /* 34 */ { UD_Isysenter, O_NONE, O_NONE, O_NONE, P_inv64|P_none }, /* 35 */ { UD_Isysexit, O_NONE, O_NONE, O_NONE, P_none }, /* 36 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 37 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 38 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 39 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 40 */ { UD_Icmovo, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 41 */ { UD_Icmovno, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 42 */ { UD_Icmovb, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 43 */ { UD_Icmovae, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 44 */ { UD_Icmovz, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 45 */ { UD_Icmovnz, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 46 */ { UD_Icmovbe, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 47 */ { UD_Icmova, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 48 */ { UD_Icmovs, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 49 */ { UD_Icmovns, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 4A */ { UD_Icmovp, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 4B */ { UD_Icmovnp, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 4C */ { UD_Icmovl, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 4D */ { UD_Icmovge, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 4E */ { UD_Icmovle, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 4F */ { UD_Icmovg, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 50 */ { UD_Imovmskps, O_Gd, O_VR, O_NONE, P_oso|P_rexr|P_rexb }, /* 51 */ { UD_Isqrtps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 52 */ { UD_Irsqrtps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 53 */ { UD_Ircpps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 54 */ { UD_Iandps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 55 */ { UD_Iandnps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 56 */ { UD_Iorps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 57 */ { UD_Ixorps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 58 */ { UD_Iaddps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 59 */ { UD_Imulps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 5A */ { UD_Icvtps2pd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 5B */ { UD_Icvtdq2ps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 5C */ { UD_Isubps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 5D */ { UD_Iminps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 5E */ { UD_Idivps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 5F */ { UD_Imaxps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 60 */ { UD_Ipunpcklbw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 61 */ { UD_Ipunpcklwd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 62 */ { UD_Ipunpckldq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 63 */ { UD_Ipacksswb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 64 */ { UD_Ipcmpgtb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 65 */ { UD_Ipcmpgtw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 66 */ { UD_Ipcmpgtd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 67 */ { UD_Ipackuswb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 68 */ { UD_Ipunpckhbw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 69 */ { UD_Ipunpckhwd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 6A */ { UD_Ipunpckhdq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 6B */ { UD_Ipackssdw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 6C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6E */ { UD_Imovd, O_P, O_Ex, O_NONE, P_c2|P_aso|P_rexr|P_rexx|P_rexb }, /* 6F */ { UD_Imovq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 70 */ { UD_Ipshufw, O_P, O_Q, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 71 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_71__REG }, /* 72 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_72__REG }, /* 73 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_73__REG }, /* 74 */ { UD_Ipcmpeqb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 75 */ { UD_Ipcmpeqw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 76 */ { UD_Ipcmpeqd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 77 */ { UD_Iemms, O_NONE, O_NONE, O_NONE, P_none }, /* 78 */ { UD_Igrp_mode, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_78__MODE }, /* 79 */ { UD_Igrp_mode, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_79__MODE }, /* 7A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7E */ { UD_Imovd, O_Ex, O_P, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 7F */ { UD_Imovq, O_Q, O_P, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 80 */ { UD_Ijo, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, /* 81 */ { UD_Ijno, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, /* 82 */ { UD_Ijb, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, /* 83 */ { UD_Ijae, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, /* 84 */ { UD_Ijz, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, /* 85 */ { UD_Ijnz, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, /* 86 */ { UD_Ijbe, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, /* 87 */ { UD_Ija, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, /* 88 */ { UD_Ijs, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, /* 89 */ { UD_Ijns, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, /* 8A */ { UD_Ijp, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, /* 8B */ { UD_Ijnp, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, /* 8C */ { UD_Ijl, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, /* 8D */ { UD_Ijge, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, /* 8E */ { UD_Ijle, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, /* 8F */ { UD_Ijg, O_Jz, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_oso }, /* 90 */ { UD_Iseto, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 91 */ { UD_Isetno, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 92 */ { UD_Isetb, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 93 */ { UD_Isetnb, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 94 */ { UD_Isetz, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 95 */ { UD_Isetnz, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 96 */ { UD_Isetbe, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 97 */ { UD_Iseta, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 98 */ { UD_Isets, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 99 */ { UD_Isetns, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 9A */ { UD_Isetp, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 9B */ { UD_Isetnp, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 9C */ { UD_Isetl, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 9D */ { UD_Isetge, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 9E */ { UD_Isetle, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 9F */ { UD_Isetg, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* A0 */ { UD_Ipush, O_FS, O_NONE, O_NONE, P_none }, /* A1 */ { UD_Ipop, O_FS, O_NONE, O_NONE, P_none }, /* A2 */ { UD_Icpuid, O_NONE, O_NONE, O_NONE, P_none }, /* A3 */ { UD_Ibt, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* A4 */ { UD_Ishld, O_Ev, O_Gv, O_Ib, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* A5 */ { UD_Ishld, O_Ev, O_Gv, O_CL, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* A6 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_A6__MOD }, /* A7 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_A7__MOD }, /* A8 */ { UD_Ipush, O_GS, O_NONE, O_NONE, P_none }, /* A9 */ { UD_Ipop, O_GS, O_NONE, O_NONE, P_none }, /* AA */ { UD_Irsm, O_NONE, O_NONE, O_NONE, P_none }, /* AB */ { UD_Ibts, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* AC */ { UD_Ishrd, O_Ev, O_Gv, O_Ib, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* AD */ { UD_Ishrd, O_Ev, O_Gv, O_CL, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* AE */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_AE__REG }, /* AF */ { UD_Iimul, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* B0 */ { UD_Icmpxchg, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* B1 */ { UD_Icmpxchg, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* B2 */ { UD_Ilss, O_Gz, O_M, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* B3 */ { UD_Ibtr, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* B4 */ { UD_Ilfs, O_Gz, O_M, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* B5 */ { UD_Ilgs, O_Gz, O_M, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* B6 */ { UD_Imovzx, O_Gv, O_Eb, O_NONE, P_c2|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* B7 */ { UD_Imovzx, O_Gv, O_Ew, O_NONE, P_c2|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* B8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BA */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_BA__REG }, /* BB */ { UD_Ibtc, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* BC */ { UD_Ibsf, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* BD */ { UD_Ibsr, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* BE */ { UD_Imovsx, O_Gv, O_Eb, O_NONE, P_c2|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* BF */ { UD_Imovsx, O_Gv, O_Ew, O_NONE, P_c2|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* C0 */ { UD_Ixadd, O_Eb, O_Gb, O_NONE, P_aso|P_oso|P_rexr|P_rexx|P_rexb }, /* C1 */ { UD_Ixadd, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* C2 */ { UD_Icmpps, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* C3 */ { UD_Imovnti, O_M, O_Gvw, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* C4 */ { UD_Ipinsrw, O_P, O_Ew, O_Ib, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* C5 */ { UD_Ipextrw, O_Gd, O_PR, O_Ib, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* C6 */ { UD_Ishufps, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* C7 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_C7__REG }, /* C8 */ { UD_Ibswap, O_rAXr8, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, /* C9 */ { UD_Ibswap, O_rCXr9, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, /* CA */ { UD_Ibswap, O_rDXr10, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, /* CB */ { UD_Ibswap, O_rBXr11, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, /* CC */ { UD_Ibswap, O_rSPr12, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, /* CD */ { UD_Ibswap, O_rBPr13, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, /* CE */ { UD_Ibswap, O_rSIr14, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, /* CF */ { UD_Ibswap, O_rDIr15, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, /* D0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D1 */ { UD_Ipsrlw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* D2 */ { UD_Ipsrld, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* D3 */ { UD_Ipsrlq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* D4 */ { UD_Ipaddq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* D5 */ { UD_Ipmullw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* D6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D7 */ { UD_Ipmovmskb, O_Gd, O_PR, O_NONE, P_oso|P_rexr|P_rexb }, /* D8 */ { UD_Ipsubusb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* D9 */ { UD_Ipsubusw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* DA */ { UD_Ipminub, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* DB */ { UD_Ipand, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* DC */ { UD_Ipaddusb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* DD */ { UD_Ipaddusw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* DE */ { UD_Ipmaxub, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* DF */ { UD_Ipandn, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* E0 */ { UD_Ipavgb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* E1 */ { UD_Ipsraw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* E2 */ { UD_Ipsrad, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* E3 */ { UD_Ipavgw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* E4 */ { UD_Ipmulhuw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* E5 */ { UD_Ipmulhw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* E6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E7 */ { UD_Imovntq, O_M, O_P, O_NONE, P_none }, /* E8 */ { UD_Ipsubsb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* E9 */ { UD_Ipsubsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* EA */ { UD_Ipminsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* EB */ { UD_Ipor, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* EC */ { UD_Ipaddsb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* ED */ { UD_Ipaddsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* EE */ { UD_Ipmaxsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* EF */ { UD_Ipxor, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* F0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F1 */ { UD_Ipsllw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* F2 */ { UD_Ipslld, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* F3 */ { UD_Ipsllq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* F4 */ { UD_Ipmuludq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* F5 */ { UD_Ipmaddwd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* F6 */ { UD_Ipsadbw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* F7 */ { UD_Imaskmovq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* F8 */ { UD_Ipsubb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* F9 */ { UD_Ipsubw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* FA */ { UD_Ipsubd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* FB */ { UD_Ipsubq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* FC */ { UD_Ipaddb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* FD */ { UD_Ipaddw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* FE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_00__reg[8] = { /* 00 */ { UD_Isldt, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Istr, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Illdt, O_Ew, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Iltr, O_Ew, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Iverr, O_Ew, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 05 */ { UD_Iverw, O_Ew, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_01__reg[8] = { /* 00 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_00__MOD }, /* 01 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_01__MOD }, /* 02 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_02__MOD }, /* 03 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_03__MOD }, /* 04 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_04__MOD }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_06__MOD }, /* 07 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_07__MOD }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_00__mod[2] = { /* 00 */ { UD_Isgdt, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Igrp_rm, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_00__mod__op_01__rm[8] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM__OP_01__VENDOR }, /* 02 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM__OP_02__VENDOR }, /* 03 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM__OP_03__VENDOR }, /* 04 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM__OP_04__VENDOR }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_00__mod__op_01__rm__op_01__vendor[3] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Ivmcall, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Ivmcall, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_00__mod__op_01__rm__op_02__vendor[3] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Ivmlaunch, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Ivmlaunch, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_00__mod__op_01__rm__op_03__vendor[3] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Ivmresume, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Ivmresume, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_00__mod__op_01__rm__op_04__vendor[3] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Ivmxoff, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Ivmxoff, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_01__mod[2] = { /* 00 */ { UD_Isidt, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Igrp_rm, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_01__MOD__OP_01__RM }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_01__mod__op_01__rm[8] = { /* 00 */ { UD_Imonitor, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Imwait, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_02__mod[2] = { /* 00 */ { UD_Ilgdt, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Igrp_rm, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_02__MOD__OP_01__RM }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_02__mod__op_01__rm[8] = { /* 00 */ { UD_Ixgetbv, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Ixsetbv, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_03__mod[2] = { /* 00 */ { UD_Ilidt, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Igrp_rm, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_03__mod__op_01__rm[8] = { /* 00 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_00__VENDOR }, /* 01 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_01__VENDOR }, /* 02 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_02__VENDOR }, /* 03 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_03__VENDOR }, /* 04 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_04__VENDOR }, /* 05 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_05__VENDOR }, /* 06 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_06__VENDOR }, /* 07 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_07__VENDOR }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_03__mod__op_01__rm__op_00__vendor[3] = { /* 00 */ { UD_Ivmrun, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Ivmrun, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_03__mod__op_01__rm__op_01__vendor[3] = { /* 00 */ { UD_Ivmmcall, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Ivmmcall, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_03__mod__op_01__rm__op_02__vendor[3] = { /* 00 */ { UD_Ivmload, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Ivmload, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_03__mod__op_01__rm__op_03__vendor[3] = { /* 00 */ { UD_Ivmsave, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Ivmsave, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_03__mod__op_01__rm__op_04__vendor[3] = { /* 00 */ { UD_Istgi, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Istgi, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_03__mod__op_01__rm__op_05__vendor[3] = { /* 00 */ { UD_Iclgi, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Iclgi, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_03__mod__op_01__rm__op_06__vendor[3] = { /* 00 */ { UD_Iskinit, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Iskinit, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_03__mod__op_01__rm__op_07__vendor[3] = { /* 00 */ { UD_Iinvlpga, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Iinvlpga, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_04__mod[2] = { /* 00 */ { UD_Ismsw, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_06__mod[2] = { /* 00 */ { UD_Ilmsw, O_Ew, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_07__mod[2] = { /* 00 */ { UD_Iinvlpg, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Igrp_rm, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_07__MOD__OP_01__RM }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_07__mod__op_01__rm[8] = { /* 00 */ { UD_Iswapgs, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_01__REG__OP_07__MOD__OP_01__RM__OP_01__VENDOR }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_01__reg__op_07__mod__op_01__rm__op_01__vendor[3] = { /* 00 */ { UD_Irdtscp, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Irdtscp, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_0d__reg[8] = { /* 00 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 05 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 06 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 07 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__0f__op_18__reg[8] = { /* 00 */ { UD_Iprefetchnta, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Iprefetcht0, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Iprefetcht1, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Iprefetcht2, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_71__reg[8] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Ipsrlw, O_PR, O_Ib, O_NONE, P_none }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Ipsraw, O_PR, O_Ib, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Ipsllw, O_PR, O_Ib, O_NONE, P_none }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_72__reg[8] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Ipsrld, O_PR, O_Ib, O_NONE, P_none }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Ipsrad, O_PR, O_Ib, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Ipslld, O_PR, O_Ib, O_NONE, P_none }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_73__reg[8] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Ipsrlq, O_PR, O_Ib, O_NONE, P_none }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Ipsllq, O_PR, O_Ib, O_NONE, P_none }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_78__mode[3] = { /* 00 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_78__MODE__OP_00__VENDOR }, /* 01 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_78__MODE__OP_01__VENDOR }, /* 02 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_78__MODE__OP_02__VENDOR }, }; static struct ud_itab_entry itab__0f__op_78__mode__op_00__vendor[3] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Ivmread, O_Ed, O_Gd, O_NONE, P_def64|P_aso|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ivmread, O_Ed, O_Gd, O_NONE, P_def64|P_aso|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__0f__op_78__mode__op_01__vendor[3] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Ivmread, O_Ed, O_Gd, O_NONE, P_def64|P_aso|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ivmread, O_Ed, O_Gd, O_NONE, P_def64|P_aso|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__0f__op_78__mode__op_02__vendor[3] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Ivmread, O_Eq, O_Gq, O_NONE, P_def64|P_aso|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ivmread, O_Eq, O_Gq, O_NONE, P_def64|P_aso|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__0f__op_79__mode[3] = { /* 00 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_79__MODE__OP_00__VENDOR }, /* 01 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_79__MODE__OP_01__VENDOR }, /* 02 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_79__MODE__OP_02__VENDOR }, }; static struct ud_itab_entry itab__0f__op_79__mode__op_00__vendor[3] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Ivmwrite, O_Gd, O_Ed, O_NONE, P_def64|P_aso|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ivmwrite, O_Gd, O_Ed, O_NONE, P_def64|P_aso|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__0f__op_79__mode__op_01__vendor[3] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Ivmwrite, O_Gd, O_Ed, O_NONE, P_def64|P_aso|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ivmwrite, O_Gd, O_Ed, O_NONE, P_def64|P_aso|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__0f__op_79__mode__op_02__vendor[3] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Ivmwrite, O_Gq, O_Eq, O_NONE, P_def64|P_aso|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ivmwrite, O_Gq, O_Eq, O_NONE, P_def64|P_aso|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__0f__op_a6__mod[2] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Igrp_rm, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_A6__MOD__OP_01__RM }, }; static struct ud_itab_entry itab__0f__op_a6__mod__op_01__rm[8] = { /* 00 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_A6__MOD__OP_01__RM__OP_00__REG }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_a6__mod__op_01__rm__op_00__reg[8] = { /* 00 */ { UD_Imontmul, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Ixsha1, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Ixsha256, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_a7__mod[2] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Igrp_rm, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_A7__MOD__OP_01__RM }, }; static struct ud_itab_entry itab__0f__op_a7__mod__op_01__rm[8] = { /* 00 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_A7__MOD__OP_01__RM__OP_00__REG }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_a7__mod__op_01__rm__op_00__reg[8] = { /* 00 */ { UD_Ixstore, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Ixcryptecb, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Ixcryptcbc, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Ixcryptctr, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Ixcryptcfb, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Ixcryptofb, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_ae__reg[8] = { /* 00 */ { UD_Ifxsave, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Ifxrstor, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ildmxcsr, O_Md, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Istmxcsr, O_Md, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_AE__REG__OP_04__MOD }, /* 05 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_AE__REG__OP_05__MOD }, /* 06 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_AE__REG__OP_06__MOD }, /* 07 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_AE__REG__OP_07__MOD }, }; static struct ud_itab_entry itab__0f__op_ae__reg__op_04__mod[2] = { /* 00 */ { UD_Ixsave, O_M, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_ae__reg__op_05__mod[2] = { /* 00 */ { UD_Ixrstor, O_M, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Igrp_rm, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_AE__REG__OP_05__MOD__OP_01__RM }, }; static struct ud_itab_entry itab__0f__op_ae__reg__op_05__mod__op_01__rm[8] = { /* 00 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_ae__reg__op_06__mod[2] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Igrp_rm, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_AE__REG__OP_06__MOD__OP_01__RM }, }; static struct ud_itab_entry itab__0f__op_ae__reg__op_06__mod__op_01__rm[8] = { /* 00 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_ae__reg__op_07__mod[2] = { /* 00 */ { UD_Iclflush, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Igrp_rm, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_AE__REG__OP_07__MOD__OP_01__RM }, }; static struct ud_itab_entry itab__0f__op_ae__reg__op_07__mod__op_01__rm[8] = { /* 00 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__0f__op_ba__reg[8] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Ibt, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 05 */ { UD_Ibts, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 06 */ { UD_Ibtr, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 07 */ { UD_Ibtc, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__0f__op_c7__reg[8] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Icmpxchg8b, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_C7__REG__OP_06__VENDOR }, /* 07 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_C7__REG__OP_07__VENDOR }, }; static struct ud_itab_entry itab__0f__op_c7__reg__op_06__vendor[3] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Ivmptrld, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ivmptrld, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__0f__op_c7__reg__op_07__vendor[3] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Ivmptrst, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ivmptrst, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__0f__op_d9__mod[2] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Igrp_x87, O_NONE, O_NONE, O_NONE, ITAB__0F__OP_D9__MOD__OP_01__X87 }, }; static struct ud_itab_entry itab__0f__op_d9__mod__op_01__x87[64] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 08 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 09 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 10 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 11 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 12 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 13 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 14 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 15 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 16 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 17 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 18 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 19 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 20 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 21 */ { UD_Ifabs, O_NONE, O_NONE, O_NONE, P_none }, /* 22 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 23 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 24 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 25 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 26 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 27 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 28 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 29 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 30 */ { UD_If2xm1, O_NONE, O_NONE, O_NONE, P_none }, /* 31 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 32 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 33 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 34 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 35 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 36 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 37 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 38 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 39 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__1byte[256] = { /* 00 */ { UD_Iadd, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Iadd, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Iadd, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Iadd, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Iadd, O_AL, O_Ib, O_NONE, P_none }, /* 05 */ { UD_Iadd, O_rAX, O_Iz, O_NONE, P_oso|P_rexw }, /* 06 */ { UD_Ipush, O_ES, O_NONE, O_NONE, P_inv64|P_none }, /* 07 */ { UD_Ipop, O_ES, O_NONE, O_NONE, P_inv64|P_none }, /* 08 */ { UD_Ior, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 09 */ { UD_Ior, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0A */ { UD_Ior, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0B */ { UD_Ior, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0C */ { UD_Ior, O_AL, O_Ib, O_NONE, P_none }, /* 0D */ { UD_Ior, O_rAX, O_Iz, O_NONE, P_oso|P_rexw }, /* 0E */ { UD_Ipush, O_CS, O_NONE, O_NONE, P_inv64|P_none }, /* 0F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 10 */ { UD_Iadc, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 11 */ { UD_Iadc, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 12 */ { UD_Iadc, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 13 */ { UD_Iadc, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 14 */ { UD_Iadc, O_AL, O_Ib, O_NONE, P_none }, /* 15 */ { UD_Iadc, O_rAX, O_Iz, O_NONE, P_oso|P_rexw }, /* 16 */ { UD_Ipush, O_SS, O_NONE, O_NONE, P_inv64|P_none }, /* 17 */ { UD_Ipop, O_SS, O_NONE, O_NONE, P_inv64|P_none }, /* 18 */ { UD_Isbb, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 19 */ { UD_Isbb, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1A */ { UD_Isbb, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1B */ { UD_Isbb, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1C */ { UD_Isbb, O_AL, O_Ib, O_NONE, P_none }, /* 1D */ { UD_Isbb, O_rAX, O_Iz, O_NONE, P_oso|P_rexw }, /* 1E */ { UD_Ipush, O_DS, O_NONE, O_NONE, P_inv64|P_none }, /* 1F */ { UD_Ipop, O_DS, O_NONE, O_NONE, P_inv64|P_none }, /* 20 */ { UD_Iand, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 21 */ { UD_Iand, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 22 */ { UD_Iand, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 23 */ { UD_Iand, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 24 */ { UD_Iand, O_AL, O_Ib, O_NONE, P_none }, /* 25 */ { UD_Iand, O_rAX, O_Iz, O_NONE, P_oso|P_rexw }, /* 26 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 27 */ { UD_Idaa, O_NONE, O_NONE, O_NONE, P_inv64|P_none }, /* 28 */ { UD_Isub, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 29 */ { UD_Isub, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 2A */ { UD_Isub, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 2B */ { UD_Isub, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 2C */ { UD_Isub, O_AL, O_Ib, O_NONE, P_none }, /* 2D */ { UD_Isub, O_rAX, O_Iz, O_NONE, P_oso|P_rexw }, /* 2E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2F */ { UD_Idas, O_NONE, O_NONE, O_NONE, P_inv64|P_none }, /* 30 */ { UD_Ixor, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 31 */ { UD_Ixor, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 32 */ { UD_Ixor, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 33 */ { UD_Ixor, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 34 */ { UD_Ixor, O_AL, O_Ib, O_NONE, P_none }, /* 35 */ { UD_Ixor, O_rAX, O_Iz, O_NONE, P_oso|P_rexw }, /* 36 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 37 */ { UD_Iaaa, O_NONE, O_NONE, O_NONE, P_inv64|P_none }, /* 38 */ { UD_Icmp, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 39 */ { UD_Icmp, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 3A */ { UD_Icmp, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 3B */ { UD_Icmp, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 3C */ { UD_Icmp, O_AL, O_Ib, O_NONE, P_none }, /* 3D */ { UD_Icmp, O_rAX, O_Iz, O_NONE, P_oso|P_rexw }, /* 3E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3F */ { UD_Iaas, O_NONE, O_NONE, O_NONE, P_inv64|P_none }, /* 40 */ { UD_Iinc, O_eAX, O_NONE, O_NONE, P_oso }, /* 41 */ { UD_Iinc, O_eCX, O_NONE, O_NONE, P_oso }, /* 42 */ { UD_Iinc, O_eDX, O_NONE, O_NONE, P_oso }, /* 43 */ { UD_Iinc, O_eBX, O_NONE, O_NONE, P_oso }, /* 44 */ { UD_Iinc, O_eSP, O_NONE, O_NONE, P_oso }, /* 45 */ { UD_Iinc, O_eBP, O_NONE, O_NONE, P_oso }, /* 46 */ { UD_Iinc, O_eSI, O_NONE, O_NONE, P_oso }, /* 47 */ { UD_Iinc, O_eDI, O_NONE, O_NONE, P_oso }, /* 48 */ { UD_Idec, O_eAX, O_NONE, O_NONE, P_oso }, /* 49 */ { UD_Idec, O_eCX, O_NONE, O_NONE, P_oso }, /* 4A */ { UD_Idec, O_eDX, O_NONE, O_NONE, P_oso }, /* 4B */ { UD_Idec, O_eBX, O_NONE, O_NONE, P_oso }, /* 4C */ { UD_Idec, O_eSP, O_NONE, O_NONE, P_oso }, /* 4D */ { UD_Idec, O_eBP, O_NONE, O_NONE, P_oso }, /* 4E */ { UD_Idec, O_eSI, O_NONE, O_NONE, P_oso }, /* 4F */ { UD_Idec, O_eDI, O_NONE, O_NONE, P_oso }, /* 50 */ { UD_Ipush, O_rAXr8, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, /* 51 */ { UD_Ipush, O_rCXr9, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, /* 52 */ { UD_Ipush, O_rDXr10, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, /* 53 */ { UD_Ipush, O_rBXr11, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, /* 54 */ { UD_Ipush, O_rSPr12, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, /* 55 */ { UD_Ipush, O_rBPr13, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, /* 56 */ { UD_Ipush, O_rSIr14, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, /* 57 */ { UD_Ipush, O_rDIr15, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, /* 58 */ { UD_Ipop, O_rAXr8, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, /* 59 */ { UD_Ipop, O_rCXr9, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, /* 5A */ { UD_Ipop, O_rDXr10, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, /* 5B */ { UD_Ipop, O_rBXr11, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, /* 5C */ { UD_Ipop, O_rSPr12, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, /* 5D */ { UD_Ipop, O_rBPr13, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, /* 5E */ { UD_Ipop, O_rSIr14, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, /* 5F */ { UD_Ipop, O_rDIr15, O_NONE, O_NONE, P_def64|P_depM|P_oso|P_rexb }, /* 60 */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_60__OSIZE }, /* 61 */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_61__OSIZE }, /* 62 */ { UD_Ibound, O_Gv, O_M, O_NONE, P_inv64|P_aso|P_oso }, /* 63 */ { UD_Igrp_mode, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_63__MODE }, /* 64 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 65 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 66 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 67 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 68 */ { UD_Ipush, O_Iz, O_NONE, O_NONE, P_c1|P_oso }, /* 69 */ { UD_Iimul, O_Gv, O_Ev, O_Iz, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 6A */ { UD_Ipush, O_Ib, O_NONE, O_NONE, P_none }, /* 6B */ { UD_Iimul, O_Gv, O_Ev, O_Ib, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 6C */ { UD_Iinsb, O_NONE, O_NONE, O_NONE, P_none }, /* 6D */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_6D__OSIZE }, /* 6E */ { UD_Ioutsb, O_NONE, O_NONE, O_NONE, P_none }, /* 6F */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_6F__OSIZE }, /* 70 */ { UD_Ijo, O_Jb, O_NONE, O_NONE, P_none }, /* 71 */ { UD_Ijno, O_Jb, O_NONE, O_NONE, P_none }, /* 72 */ { UD_Ijb, O_Jb, O_NONE, O_NONE, P_none }, /* 73 */ { UD_Ijae, O_Jb, O_NONE, O_NONE, P_none }, /* 74 */ { UD_Ijz, O_Jb, O_NONE, O_NONE, P_none }, /* 75 */ { UD_Ijnz, O_Jb, O_NONE, O_NONE, P_none }, /* 76 */ { UD_Ijbe, O_Jb, O_NONE, O_NONE, P_none }, /* 77 */ { UD_Ija, O_Jb, O_NONE, O_NONE, P_none }, /* 78 */ { UD_Ijs, O_Jb, O_NONE, O_NONE, P_none }, /* 79 */ { UD_Ijns, O_Jb, O_NONE, O_NONE, P_none }, /* 7A */ { UD_Ijp, O_Jb, O_NONE, O_NONE, P_none }, /* 7B */ { UD_Ijnp, O_Jb, O_NONE, O_NONE, P_none }, /* 7C */ { UD_Ijl, O_Jb, O_NONE, O_NONE, P_none }, /* 7D */ { UD_Ijge, O_Jb, O_NONE, O_NONE, P_none }, /* 7E */ { UD_Ijle, O_Jb, O_NONE, O_NONE, P_none }, /* 7F */ { UD_Ijg, O_Jb, O_NONE, O_NONE, P_none }, /* 80 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_80__REG }, /* 81 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_81__REG }, /* 82 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_82__REG }, /* 83 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_83__REG }, /* 84 */ { UD_Itest, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 85 */ { UD_Itest, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 86 */ { UD_Ixchg, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 87 */ { UD_Ixchg, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 88 */ { UD_Imov, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 89 */ { UD_Imov, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 8A */ { UD_Imov, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 8B */ { UD_Imov, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 8C */ { UD_Imov, O_Ev, O_S, O_NONE, P_aso|P_oso|P_rexr|P_rexx|P_rexb }, /* 8D */ { UD_Ilea, O_Gv, O_M, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 8E */ { UD_Imov, O_S, O_Ev, O_NONE, P_aso|P_oso|P_rexr|P_rexx|P_rexb }, /* 8F */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_8F__REG }, /* 90 */ { UD_Ixchg, O_rAXr8, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, /* 91 */ { UD_Ixchg, O_rCXr9, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, /* 92 */ { UD_Ixchg, O_rDXr10, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, /* 93 */ { UD_Ixchg, O_rBXr11, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, /* 94 */ { UD_Ixchg, O_rSPr12, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, /* 95 */ { UD_Ixchg, O_rBPr13, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, /* 96 */ { UD_Ixchg, O_rSIr14, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, /* 97 */ { UD_Ixchg, O_rDIr15, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, /* 98 */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_98__OSIZE }, /* 99 */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_99__OSIZE }, /* 9A */ { UD_Icall, O_Ap, O_NONE, O_NONE, P_inv64|P_oso }, /* 9B */ { UD_Iwait, O_NONE, O_NONE, O_NONE, P_none }, /* 9C */ { UD_Igrp_mode, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_9C__MODE }, /* 9D */ { UD_Igrp_mode, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_9D__MODE }, /* 9E */ { UD_Isahf, O_NONE, O_NONE, O_NONE, P_none }, /* 9F */ { UD_Ilahf, O_NONE, O_NONE, O_NONE, P_none }, /* A0 */ { UD_Imov, O_AL, O_Ob, O_NONE, P_none }, /* A1 */ { UD_Imov, O_rAX, O_Ov, O_NONE, P_aso|P_oso|P_rexw }, /* A2 */ { UD_Imov, O_Ob, O_AL, O_NONE, P_none }, /* A3 */ { UD_Imov, O_Ov, O_rAX, O_NONE, P_aso|P_oso|P_rexw }, /* A4 */ { UD_Imovsb, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_none }, /* A5 */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_A5__OSIZE }, /* A6 */ { UD_Icmpsb, O_NONE, O_NONE, O_NONE, P_none }, /* A7 */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_A7__OSIZE }, /* A8 */ { UD_Itest, O_AL, O_Ib, O_NONE, P_none }, /* A9 */ { UD_Itest, O_rAX, O_Iz, O_NONE, P_oso|P_rexw }, /* AA */ { UD_Istosb, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_none }, /* AB */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_AB__OSIZE }, /* AC */ { UD_Ilodsb, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_none }, /* AD */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_AD__OSIZE }, /* AE */ { UD_Iscasb, O_NONE, O_NONE, O_NONE, P_none }, /* AF */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_AF__OSIZE }, /* B0 */ { UD_Imov, O_ALr8b, O_Ib, O_NONE, P_rexb }, /* B1 */ { UD_Imov, O_CLr9b, O_Ib, O_NONE, P_rexb }, /* B2 */ { UD_Imov, O_DLr10b, O_Ib, O_NONE, P_rexb }, /* B3 */ { UD_Imov, O_BLr11b, O_Ib, O_NONE, P_rexb }, /* B4 */ { UD_Imov, O_AHr12b, O_Ib, O_NONE, P_rexb }, /* B5 */ { UD_Imov, O_CHr13b, O_Ib, O_NONE, P_rexb }, /* B6 */ { UD_Imov, O_DHr14b, O_Ib, O_NONE, P_rexb }, /* B7 */ { UD_Imov, O_BHr15b, O_Ib, O_NONE, P_rexb }, /* B8 */ { UD_Imov, O_rAXr8, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, /* B9 */ { UD_Imov, O_rCXr9, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, /* BA */ { UD_Imov, O_rDXr10, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, /* BB */ { UD_Imov, O_rBXr11, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, /* BC */ { UD_Imov, O_rSPr12, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, /* BD */ { UD_Imov, O_rBPr13, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, /* BE */ { UD_Imov, O_rSIr14, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, /* BF */ { UD_Imov, O_rDIr15, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, /* C0 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_C0__REG }, /* C1 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_C1__REG }, /* C2 */ { UD_Iret, O_Iw, O_NONE, O_NONE, P_none }, /* C3 */ { UD_Iret, O_NONE, O_NONE, O_NONE, P_none }, /* C4 */ { UD_Iles, O_Gv, O_M, O_NONE, P_inv64|P_aso|P_oso }, /* C5 */ { UD_Ilds, O_Gv, O_M, O_NONE, P_inv64|P_aso|P_oso }, /* C6 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_C6__REG }, /* C7 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_C7__REG }, /* C8 */ { UD_Ienter, O_Iw, O_Ib, O_NONE, P_def64|P_depM|P_none }, /* C9 */ { UD_Ileave, O_NONE, O_NONE, O_NONE, P_none }, /* CA */ { UD_Iretf, O_Iw, O_NONE, O_NONE, P_none }, /* CB */ { UD_Iretf, O_NONE, O_NONE, O_NONE, P_none }, /* CC */ { UD_Iint3, O_NONE, O_NONE, O_NONE, P_none }, /* CD */ { UD_Iint, O_Ib, O_NONE, O_NONE, P_none }, /* CE */ { UD_Iinto, O_NONE, O_NONE, O_NONE, P_inv64|P_none }, /* CF */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_CF__OSIZE }, /* D0 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_D0__REG }, /* D1 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_D1__REG }, /* D2 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_D2__REG }, /* D3 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_D3__REG }, /* D4 */ { UD_Iaam, O_Ib, O_NONE, O_NONE, P_inv64|P_none }, /* D5 */ { UD_Iaad, O_Ib, O_NONE, O_NONE, P_inv64|P_none }, /* D6 */ { UD_Isalc, O_NONE, O_NONE, O_NONE, P_inv64|P_none }, /* D7 */ { UD_Ixlatb, O_NONE, O_NONE, O_NONE, P_rexw }, /* D8 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_D8__MOD }, /* D9 */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_D9__MOD }, /* DA */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DA__MOD }, /* DB */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DB__MOD }, /* DC */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DC__MOD }, /* DD */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DD__MOD }, /* DE */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DE__MOD }, /* DF */ { UD_Igrp_mod, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DF__MOD }, /* E0 */ { UD_Iloopnz, O_Jb, O_NONE, O_NONE, P_none }, /* E1 */ { UD_Iloope, O_Jb, O_NONE, O_NONE, P_none }, /* E2 */ { UD_Iloop, O_Jb, O_NONE, O_NONE, P_none }, /* E3 */ { UD_Igrp_asize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_E3__ASIZE }, /* E4 */ { UD_Iin, O_AL, O_Ib, O_NONE, P_none }, /* E5 */ { UD_Iin, O_eAX, O_Ib, O_NONE, P_oso }, /* E6 */ { UD_Iout, O_Ib, O_AL, O_NONE, P_none }, /* E7 */ { UD_Iout, O_Ib, O_eAX, O_NONE, P_oso }, /* E8 */ { UD_Icall, O_Jz, O_NONE, O_NONE, P_def64|P_oso }, /* E9 */ { UD_Ijmp, O_Jz, O_NONE, O_NONE, P_def64|P_depM|P_oso }, /* EA */ { UD_Ijmp, O_Ap, O_NONE, O_NONE, P_inv64|P_none }, /* EB */ { UD_Ijmp, O_Jb, O_NONE, O_NONE, P_none }, /* EC */ { UD_Iin, O_AL, O_DX, O_NONE, P_none }, /* ED */ { UD_Iin, O_eAX, O_DX, O_NONE, P_oso }, /* EE */ { UD_Iout, O_DX, O_AL, O_NONE, P_none }, /* EF */ { UD_Iout, O_DX, O_eAX, O_NONE, P_oso }, /* F0 */ { UD_Ilock, O_NONE, O_NONE, O_NONE, P_none }, /* F1 */ { UD_Iint1, O_NONE, O_NONE, O_NONE, P_none }, /* F2 */ { UD_Irepne, O_NONE, O_NONE, O_NONE, P_none }, /* F3 */ { UD_Irep, O_NONE, O_NONE, O_NONE, P_none }, /* F4 */ { UD_Ihlt, O_NONE, O_NONE, O_NONE, P_none }, /* F5 */ { UD_Icmc, O_NONE, O_NONE, O_NONE, P_none }, /* F6 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_F6__REG }, /* F7 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_F7__REG }, /* F8 */ { UD_Iclc, O_NONE, O_NONE, O_NONE, P_none }, /* F9 */ { UD_Istc, O_NONE, O_NONE, O_NONE, P_none }, /* FA */ { UD_Icli, O_NONE, O_NONE, O_NONE, P_none }, /* FB */ { UD_Isti, O_NONE, O_NONE, O_NONE, P_none }, /* FC */ { UD_Icld, O_NONE, O_NONE, O_NONE, P_none }, /* FD */ { UD_Istd, O_NONE, O_NONE, O_NONE, P_none }, /* FE */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_FE__REG }, /* FF */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_FF__REG }, }; static struct ud_itab_entry itab__1byte__op_60__osize[3] = { /* 00 */ { UD_Ipusha, O_NONE, O_NONE, O_NONE, P_inv64|P_oso }, /* 01 */ { UD_Ipushad, O_NONE, O_NONE, O_NONE, P_inv64|P_oso }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__1byte__op_61__osize[3] = { /* 00 */ { UD_Ipopa, O_NONE, O_NONE, O_NONE, P_inv64|P_oso }, /* 01 */ { UD_Ipopad, O_NONE, O_NONE, O_NONE, P_inv64|P_oso }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__1byte__op_63__mode[3] = { /* 00 */ { UD_Iarpl, O_Ew, O_Gw, O_NONE, P_inv64|P_aso }, /* 01 */ { UD_Iarpl, O_Ew, O_Gw, O_NONE, P_inv64|P_aso }, /* 02 */ { UD_Imovsxd, O_Gv, O_Ed, O_NONE, P_c2|P_aso|P_oso|P_rexw|P_rexx|P_rexr|P_rexb }, }; static struct ud_itab_entry itab__1byte__op_6d__osize[3] = { /* 00 */ { UD_Iinsw, O_NONE, O_NONE, O_NONE, P_oso }, /* 01 */ { UD_Iinsd, O_NONE, O_NONE, O_NONE, P_oso }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__1byte__op_6f__osize[3] = { /* 00 */ { UD_Ioutsw, O_NONE, O_NONE, O_NONE, P_oso }, /* 01 */ { UD_Ioutsd, O_NONE, O_NONE, O_NONE, P_oso }, /* 02 */ { UD_Ioutsq, O_NONE, O_NONE, O_NONE, P_oso }, }; static struct ud_itab_entry itab__1byte__op_80__reg[8] = { /* 00 */ { UD_Iadd, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Ior, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Iadc, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Isbb, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Iand, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 05 */ { UD_Isub, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 06 */ { UD_Ixor, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 07 */ { UD_Icmp, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__1byte__op_81__reg[8] = { /* 00 */ { UD_Iadd, O_Ev, O_Iz, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Ior, O_Ev, O_Iz, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Iadc, O_Ev, O_Iz, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Isbb, O_Ev, O_Iz, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Iand, O_Ev, O_Iz, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 05 */ { UD_Isub, O_Ev, O_Iz, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 06 */ { UD_Ixor, O_Ev, O_Iz, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 07 */ { UD_Icmp, O_Ev, O_Iz, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__1byte__op_82__reg[8] = { /* 00 */ { UD_Iadd, O_Eb, O_Ib, O_NONE, P_c1|P_inv64|P_aso|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Ior, O_Eb, O_Ib, O_NONE, P_c1|P_inv64|P_aso|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Iadc, O_Eb, O_Ib, O_NONE, P_c1|P_inv64|P_aso|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Isbb, O_Eb, O_Ib, O_NONE, P_c1|P_inv64|P_aso|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Iand, O_Eb, O_Ib, O_NONE, P_c1|P_inv64|P_aso|P_rexr|P_rexx|P_rexb }, /* 05 */ { UD_Isub, O_Eb, O_Ib, O_NONE, P_c1|P_inv64|P_aso|P_rexr|P_rexx|P_rexb }, /* 06 */ { UD_Ixor, O_Eb, O_Ib, O_NONE, P_c1|P_inv64|P_aso|P_rexr|P_rexx|P_rexb }, /* 07 */ { UD_Icmp, O_Eb, O_Ib, O_NONE, P_c1|P_inv64|P_aso|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__1byte__op_83__reg[8] = { /* 00 */ { UD_Iadd, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Ior, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Iadc, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Isbb, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Iand, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 05 */ { UD_Isub, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 06 */ { UD_Ixor, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 07 */ { UD_Icmp, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__1byte__op_8f__reg[8] = { /* 00 */ { UD_Ipop, O_Ev, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__1byte__op_98__osize[3] = { /* 00 */ { UD_Icbw, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, /* 01 */ { UD_Icwde, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, /* 02 */ { UD_Icdqe, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, }; static struct ud_itab_entry itab__1byte__op_99__osize[3] = { /* 00 */ { UD_Icwd, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, /* 01 */ { UD_Icdq, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, /* 02 */ { UD_Icqo, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, }; static struct ud_itab_entry itab__1byte__op_9c__mode[3] = { /* 00 */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_9C__MODE__OP_00__OSIZE }, /* 01 */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_9C__MODE__OP_01__OSIZE }, /* 02 */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_9C__MODE__OP_02__OSIZE }, }; static struct ud_itab_entry itab__1byte__op_9c__mode__op_00__osize[3] = { /* 00 */ { UD_Ipushfw, O_NONE, O_NONE, O_NONE, P_def64|P_oso }, /* 01 */ { UD_Ipushfd, O_NONE, O_NONE, O_NONE, P_def64|P_oso }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__1byte__op_9c__mode__op_01__osize[3] = { /* 00 */ { UD_Ipushfw, O_NONE, O_NONE, O_NONE, P_def64|P_oso }, /* 01 */ { UD_Ipushfd, O_NONE, O_NONE, O_NONE, P_def64|P_oso }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__1byte__op_9c__mode__op_02__osize[3] = { /* 00 */ { UD_Ipushfw, O_NONE, O_NONE, O_NONE, P_def64|P_oso|P_rexw }, /* 01 */ { UD_Ipushfq, O_NONE, O_NONE, O_NONE, P_def64|P_oso|P_rexw }, /* 02 */ { UD_Ipushfq, O_NONE, O_NONE, O_NONE, P_def64|P_oso|P_rexw }, }; static struct ud_itab_entry itab__1byte__op_9d__mode[3] = { /* 00 */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_9D__MODE__OP_00__OSIZE }, /* 01 */ { UD_Igrp_osize, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_9D__MODE__OP_01__OSIZE }, /* 02 */ { UD_Ipopfq, O_NONE, O_NONE, O_NONE, P_def64|P_depM|P_oso }, }; static struct ud_itab_entry itab__1byte__op_9d__mode__op_00__osize[3] = { /* 00 */ { UD_Ipopfw, O_NONE, O_NONE, O_NONE, P_def64|P_depM|P_oso }, /* 01 */ { UD_Ipopfd, O_NONE, O_NONE, O_NONE, P_def64|P_depM|P_oso }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__1byte__op_9d__mode__op_01__osize[3] = { /* 00 */ { UD_Ipopfw, O_NONE, O_NONE, O_NONE, P_def64|P_depM|P_oso }, /* 01 */ { UD_Ipopfd, O_NONE, O_NONE, O_NONE, P_def64|P_depM|P_oso }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__1byte__op_a5__osize[3] = { /* 00 */ { UD_Imovsw, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_oso|P_rexw }, /* 01 */ { UD_Imovsd, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_oso|P_rexw }, /* 02 */ { UD_Imovsq, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_oso|P_rexw }, }; static struct ud_itab_entry itab__1byte__op_a7__osize[3] = { /* 00 */ { UD_Icmpsw, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, /* 01 */ { UD_Icmpsd, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, /* 02 */ { UD_Icmpsq, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, }; static struct ud_itab_entry itab__1byte__op_ab__osize[3] = { /* 00 */ { UD_Istosw, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_oso|P_rexw }, /* 01 */ { UD_Istosd, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_oso|P_rexw }, /* 02 */ { UD_Istosq, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_oso|P_rexw }, }; static struct ud_itab_entry itab__1byte__op_ad__osize[3] = { /* 00 */ { UD_Ilodsw, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_oso|P_rexw }, /* 01 */ { UD_Ilodsd, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_oso|P_rexw }, /* 02 */ { UD_Ilodsq, O_NONE, O_NONE, O_NONE, P_ImpAddr|P_oso|P_rexw }, }; static struct ud_itab_entry itab__1byte__op_af__osize[3] = { /* 00 */ { UD_Iscasw, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, /* 01 */ { UD_Iscasd, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, /* 02 */ { UD_Iscasq, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, }; static struct ud_itab_entry itab__1byte__op_c0__reg[8] = { /* 00 */ { UD_Irol, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Iror, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ircl, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Ircr, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Ishl, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 05 */ { UD_Ishr, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 06 */ { UD_Ishl, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 07 */ { UD_Isar, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__1byte__op_c1__reg[8] = { /* 00 */ { UD_Irol, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Iror, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ircl, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Ircr, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Ishl, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 05 */ { UD_Ishr, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 06 */ { UD_Ishl, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 07 */ { UD_Isar, O_Ev, O_Ib, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__1byte__op_c6__reg[8] = { /* 00 */ { UD_Imov, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__1byte__op_c7__reg[8] = { /* 00 */ { UD_Imov, O_Ev, O_Iz, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__1byte__op_cf__osize[3] = { /* 00 */ { UD_Iiretw, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, /* 01 */ { UD_Iiretd, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, /* 02 */ { UD_Iiretq, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, }; static struct ud_itab_entry itab__1byte__op_d0__reg[8] = { /* 00 */ { UD_Irol, O_Eb, O_I1, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Iror, O_Eb, O_I1, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ircl, O_Eb, O_I1, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Ircr, O_Eb, O_I1, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Ishl, O_Eb, O_I1, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 05 */ { UD_Ishr, O_Eb, O_I1, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 06 */ { UD_Ishl, O_Eb, O_I1, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 07 */ { UD_Isar, O_Eb, O_I1, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__1byte__op_d1__reg[8] = { /* 00 */ { UD_Irol, O_Ev, O_I1, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Iror, O_Ev, O_I1, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ircl, O_Ev, O_I1, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Ircr, O_Ev, O_I1, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Ishl, O_Ev, O_I1, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 05 */ { UD_Ishr, O_Ev, O_I1, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 06 */ { UD_Ishl, O_Ev, O_I1, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 07 */ { UD_Isar, O_Ev, O_I1, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__1byte__op_d2__reg[8] = { /* 00 */ { UD_Irol, O_Eb, O_CL, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Iror, O_Eb, O_CL, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ircl, O_Eb, O_CL, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Ircr, O_Eb, O_CL, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Ishl, O_Eb, O_CL, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 05 */ { UD_Ishr, O_Eb, O_CL, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 06 */ { UD_Ishl, O_Eb, O_CL, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 07 */ { UD_Isar, O_Eb, O_CL, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__1byte__op_d3__reg[8] = { /* 00 */ { UD_Irol, O_Ev, O_CL, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Iror, O_Ev, O_CL, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ircl, O_Ev, O_CL, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Ircr, O_Ev, O_CL, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Ishl, O_Ev, O_CL, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 05 */ { UD_Ishr, O_Ev, O_CL, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 06 */ { UD_Ishl, O_Ev, O_CL, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 07 */ { UD_Isar, O_Ev, O_CL, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__1byte__op_d8__mod[2] = { /* 00 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_D8__MOD__OP_00__REG }, /* 01 */ { UD_Igrp_x87, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_D8__MOD__OP_01__X87 }, }; static struct ud_itab_entry itab__1byte__op_d8__mod__op_00__reg[8] = { /* 00 */ { UD_Ifadd, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Ifmul, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ifcom, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Ifcomp, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Ifsub, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 05 */ { UD_Ifsubr, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 06 */ { UD_Ifdiv, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 07 */ { UD_Ifdivr, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__1byte__op_d8__mod__op_01__x87[64] = { /* 00 */ { UD_Ifadd, O_ST0, O_ST0, O_NONE, P_none }, /* 01 */ { UD_Ifadd, O_ST0, O_ST1, O_NONE, P_none }, /* 02 */ { UD_Ifadd, O_ST0, O_ST2, O_NONE, P_none }, /* 03 */ { UD_Ifadd, O_ST0, O_ST3, O_NONE, P_none }, /* 04 */ { UD_Ifadd, O_ST0, O_ST4, O_NONE, P_none }, /* 05 */ { UD_Ifadd, O_ST0, O_ST5, O_NONE, P_none }, /* 06 */ { UD_Ifadd, O_ST0, O_ST6, O_NONE, P_none }, /* 07 */ { UD_Ifadd, O_ST0, O_ST7, O_NONE, P_none }, /* 08 */ { UD_Ifmul, O_ST0, O_ST0, O_NONE, P_none }, /* 09 */ { UD_Ifmul, O_ST0, O_ST1, O_NONE, P_none }, /* 0A */ { UD_Ifmul, O_ST0, O_ST2, O_NONE, P_none }, /* 0B */ { UD_Ifmul, O_ST0, O_ST3, O_NONE, P_none }, /* 0C */ { UD_Ifmul, O_ST0, O_ST4, O_NONE, P_none }, /* 0D */ { UD_Ifmul, O_ST0, O_ST5, O_NONE, P_none }, /* 0E */ { UD_Ifmul, O_ST0, O_ST6, O_NONE, P_none }, /* 0F */ { UD_Ifmul, O_ST0, O_ST7, O_NONE, P_none }, /* 10 */ { UD_Ifcom, O_ST0, O_ST0, O_NONE, P_none }, /* 11 */ { UD_Ifcom, O_ST0, O_ST1, O_NONE, P_none }, /* 12 */ { UD_Ifcom, O_ST0, O_ST2, O_NONE, P_none }, /* 13 */ { UD_Ifcom, O_ST0, O_ST3, O_NONE, P_none }, /* 14 */ { UD_Ifcom, O_ST0, O_ST4, O_NONE, P_none }, /* 15 */ { UD_Ifcom, O_ST0, O_ST5, O_NONE, P_none }, /* 16 */ { UD_Ifcom, O_ST0, O_ST6, O_NONE, P_none }, /* 17 */ { UD_Ifcom, O_ST0, O_ST7, O_NONE, P_none }, /* 18 */ { UD_Ifcomp, O_ST0, O_ST0, O_NONE, P_none }, /* 19 */ { UD_Ifcomp, O_ST0, O_ST1, O_NONE, P_none }, /* 1A */ { UD_Ifcomp, O_ST0, O_ST2, O_NONE, P_none }, /* 1B */ { UD_Ifcomp, O_ST0, O_ST3, O_NONE, P_none }, /* 1C */ { UD_Ifcomp, O_ST0, O_ST4, O_NONE, P_none }, /* 1D */ { UD_Ifcomp, O_ST0, O_ST5, O_NONE, P_none }, /* 1E */ { UD_Ifcomp, O_ST0, O_ST6, O_NONE, P_none }, /* 1F */ { UD_Ifcomp, O_ST0, O_ST7, O_NONE, P_none }, /* 20 */ { UD_Ifsub, O_ST0, O_ST0, O_NONE, P_none }, /* 21 */ { UD_Ifsub, O_ST0, O_ST1, O_NONE, P_none }, /* 22 */ { UD_Ifsub, O_ST0, O_ST2, O_NONE, P_none }, /* 23 */ { UD_Ifsub, O_ST0, O_ST3, O_NONE, P_none }, /* 24 */ { UD_Ifsub, O_ST0, O_ST4, O_NONE, P_none }, /* 25 */ { UD_Ifsub, O_ST0, O_ST5, O_NONE, P_none }, /* 26 */ { UD_Ifsub, O_ST0, O_ST6, O_NONE, P_none }, /* 27 */ { UD_Ifsub, O_ST0, O_ST7, O_NONE, P_none }, /* 28 */ { UD_Ifsubr, O_ST0, O_ST0, O_NONE, P_none }, /* 29 */ { UD_Ifsubr, O_ST0, O_ST1, O_NONE, P_none }, /* 2A */ { UD_Ifsubr, O_ST0, O_ST2, O_NONE, P_none }, /* 2B */ { UD_Ifsubr, O_ST0, O_ST3, O_NONE, P_none }, /* 2C */ { UD_Ifsubr, O_ST0, O_ST4, O_NONE, P_none }, /* 2D */ { UD_Ifsubr, O_ST0, O_ST5, O_NONE, P_none }, /* 2E */ { UD_Ifsubr, O_ST0, O_ST6, O_NONE, P_none }, /* 2F */ { UD_Ifsubr, O_ST0, O_ST7, O_NONE, P_none }, /* 30 */ { UD_Ifdiv, O_ST0, O_ST0, O_NONE, P_none }, /* 31 */ { UD_Ifdiv, O_ST0, O_ST1, O_NONE, P_none }, /* 32 */ { UD_Ifdiv, O_ST0, O_ST2, O_NONE, P_none }, /* 33 */ { UD_Ifdiv, O_ST0, O_ST3, O_NONE, P_none }, /* 34 */ { UD_Ifdiv, O_ST0, O_ST4, O_NONE, P_none }, /* 35 */ { UD_Ifdiv, O_ST0, O_ST5, O_NONE, P_none }, /* 36 */ { UD_Ifdiv, O_ST0, O_ST6, O_NONE, P_none }, /* 37 */ { UD_Ifdiv, O_ST0, O_ST7, O_NONE, P_none }, /* 38 */ { UD_Ifdivr, O_ST0, O_ST0, O_NONE, P_none }, /* 39 */ { UD_Ifdivr, O_ST0, O_ST1, O_NONE, P_none }, /* 3A */ { UD_Ifdivr, O_ST0, O_ST2, O_NONE, P_none }, /* 3B */ { UD_Ifdivr, O_ST0, O_ST3, O_NONE, P_none }, /* 3C */ { UD_Ifdivr, O_ST0, O_ST4, O_NONE, P_none }, /* 3D */ { UD_Ifdivr, O_ST0, O_ST5, O_NONE, P_none }, /* 3E */ { UD_Ifdivr, O_ST0, O_ST6, O_NONE, P_none }, /* 3F */ { UD_Ifdivr, O_ST0, O_ST7, O_NONE, P_none }, }; static struct ud_itab_entry itab__1byte__op_d9__mod[2] = { /* 00 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_D9__MOD__OP_00__REG }, /* 01 */ { UD_Igrp_x87, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_D9__MOD__OP_01__X87 }, }; static struct ud_itab_entry itab__1byte__op_d9__mod__op_00__reg[8] = { /* 00 */ { UD_Ifld, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Ifst, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Ifstp, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Ifldenv, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 05 */ { UD_Ifldcw, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 06 */ { UD_Ifnstenv, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 07 */ { UD_Ifnstcw, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__1byte__op_d9__mod__op_01__x87[64] = { /* 00 */ { UD_Ifld, O_ST0, O_ST0, O_NONE, P_none }, /* 01 */ { UD_Ifld, O_ST0, O_ST1, O_NONE, P_none }, /* 02 */ { UD_Ifld, O_ST0, O_ST2, O_NONE, P_none }, /* 03 */ { UD_Ifld, O_ST0, O_ST3, O_NONE, P_none }, /* 04 */ { UD_Ifld, O_ST0, O_ST4, O_NONE, P_none }, /* 05 */ { UD_Ifld, O_ST0, O_ST5, O_NONE, P_none }, /* 06 */ { UD_Ifld, O_ST0, O_ST6, O_NONE, P_none }, /* 07 */ { UD_Ifld, O_ST0, O_ST7, O_NONE, P_none }, /* 08 */ { UD_Ifxch, O_ST0, O_ST0, O_NONE, P_none }, /* 09 */ { UD_Ifxch, O_ST0, O_ST1, O_NONE, P_none }, /* 0A */ { UD_Ifxch, O_ST0, O_ST2, O_NONE, P_none }, /* 0B */ { UD_Ifxch, O_ST0, O_ST3, O_NONE, P_none }, /* 0C */ { UD_Ifxch, O_ST0, O_ST4, O_NONE, P_none }, /* 0D */ { UD_Ifxch, O_ST0, O_ST5, O_NONE, P_none }, /* 0E */ { UD_Ifxch, O_ST0, O_ST6, O_NONE, P_none }, /* 0F */ { UD_Ifxch, O_ST0, O_ST7, O_NONE, P_none }, /* 10 */ { UD_Ifnop, O_NONE, O_NONE, O_NONE, P_none }, /* 11 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 12 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 13 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 14 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 15 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 16 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 17 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 18 */ { UD_Ifstp1, O_ST0, O_NONE, O_NONE, P_none }, /* 19 */ { UD_Ifstp1, O_ST1, O_NONE, O_NONE, P_none }, /* 1A */ { UD_Ifstp1, O_ST2, O_NONE, O_NONE, P_none }, /* 1B */ { UD_Ifstp1, O_ST3, O_NONE, O_NONE, P_none }, /* 1C */ { UD_Ifstp1, O_ST4, O_NONE, O_NONE, P_none }, /* 1D */ { UD_Ifstp1, O_ST5, O_NONE, O_NONE, P_none }, /* 1E */ { UD_Ifstp1, O_ST6, O_NONE, O_NONE, P_none }, /* 1F */ { UD_Ifstp1, O_ST7, O_NONE, O_NONE, P_none }, /* 20 */ { UD_Ifchs, O_NONE, O_NONE, O_NONE, P_none }, /* 21 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 22 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 23 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 24 */ { UD_Iftst, O_NONE, O_NONE, O_NONE, P_none }, /* 25 */ { UD_Ifxam, O_NONE, O_NONE, O_NONE, P_none }, /* 26 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 27 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 28 */ { UD_Ifld1, O_NONE, O_NONE, O_NONE, P_none }, /* 29 */ { UD_Ifldl2t, O_NONE, O_NONE, O_NONE, P_none }, /* 2A */ { UD_Ifldl2e, O_NONE, O_NONE, O_NONE, P_none }, /* 2B */ { UD_Ifldlpi, O_NONE, O_NONE, O_NONE, P_none }, /* 2C */ { UD_Ifldlg2, O_NONE, O_NONE, O_NONE, P_none }, /* 2D */ { UD_Ifldln2, O_NONE, O_NONE, O_NONE, P_none }, /* 2E */ { UD_Ifldz, O_NONE, O_NONE, O_NONE, P_none }, /* 2F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 30 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 31 */ { UD_Ifyl2x, O_NONE, O_NONE, O_NONE, P_none }, /* 32 */ { UD_Ifptan, O_NONE, O_NONE, O_NONE, P_none }, /* 33 */ { UD_Ifpatan, O_NONE, O_NONE, O_NONE, P_none }, /* 34 */ { UD_Ifpxtract, O_NONE, O_NONE, O_NONE, P_none }, /* 35 */ { UD_Ifprem1, O_NONE, O_NONE, O_NONE, P_none }, /* 36 */ { UD_Ifdecstp, O_NONE, O_NONE, O_NONE, P_none }, /* 37 */ { UD_Ifncstp, O_NONE, O_NONE, O_NONE, P_none }, /* 38 */ { UD_Ifprem, O_NONE, O_NONE, O_NONE, P_none }, /* 39 */ { UD_Ifyl2xp1, O_NONE, O_NONE, O_NONE, P_none }, /* 3A */ { UD_Ifsqrt, O_NONE, O_NONE, O_NONE, P_none }, /* 3B */ { UD_Ifsincos, O_NONE, O_NONE, O_NONE, P_none }, /* 3C */ { UD_Ifrndint, O_NONE, O_NONE, O_NONE, P_none }, /* 3D */ { UD_Ifscale, O_NONE, O_NONE, O_NONE, P_none }, /* 3E */ { UD_Ifsin, O_NONE, O_NONE, O_NONE, P_none }, /* 3F */ { UD_Ifcos, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__1byte__op_da__mod[2] = { /* 00 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DA__MOD__OP_00__REG }, /* 01 */ { UD_Igrp_x87, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DA__MOD__OP_01__X87 }, }; static struct ud_itab_entry itab__1byte__op_da__mod__op_00__reg[8] = { /* 00 */ { UD_Ifiadd, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Ifimul, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ificom, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Ificomp, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Ifisub, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 05 */ { UD_Ifisubr, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 06 */ { UD_Ifidiv, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 07 */ { UD_Ifidivr, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__1byte__op_da__mod__op_01__x87[64] = { /* 00 */ { UD_Ifcmovb, O_ST0, O_ST0, O_NONE, P_none }, /* 01 */ { UD_Ifcmovb, O_ST0, O_ST1, O_NONE, P_none }, /* 02 */ { UD_Ifcmovb, O_ST0, O_ST2, O_NONE, P_none }, /* 03 */ { UD_Ifcmovb, O_ST0, O_ST3, O_NONE, P_none }, /* 04 */ { UD_Ifcmovb, O_ST0, O_ST4, O_NONE, P_none }, /* 05 */ { UD_Ifcmovb, O_ST0, O_ST5, O_NONE, P_none }, /* 06 */ { UD_Ifcmovb, O_ST0, O_ST6, O_NONE, P_none }, /* 07 */ { UD_Ifcmovb, O_ST0, O_ST7, O_NONE, P_none }, /* 08 */ { UD_Ifcmove, O_ST0, O_ST0, O_NONE, P_none }, /* 09 */ { UD_Ifcmove, O_ST0, O_ST1, O_NONE, P_none }, /* 0A */ { UD_Ifcmove, O_ST0, O_ST2, O_NONE, P_none }, /* 0B */ { UD_Ifcmove, O_ST0, O_ST3, O_NONE, P_none }, /* 0C */ { UD_Ifcmove, O_ST0, O_ST4, O_NONE, P_none }, /* 0D */ { UD_Ifcmove, O_ST0, O_ST5, O_NONE, P_none }, /* 0E */ { UD_Ifcmove, O_ST0, O_ST6, O_NONE, P_none }, /* 0F */ { UD_Ifcmove, O_ST0, O_ST7, O_NONE, P_none }, /* 10 */ { UD_Ifcmovbe, O_ST0, O_ST0, O_NONE, P_none }, /* 11 */ { UD_Ifcmovbe, O_ST0, O_ST1, O_NONE, P_none }, /* 12 */ { UD_Ifcmovbe, O_ST0, O_ST2, O_NONE, P_none }, /* 13 */ { UD_Ifcmovbe, O_ST0, O_ST3, O_NONE, P_none }, /* 14 */ { UD_Ifcmovbe, O_ST0, O_ST4, O_NONE, P_none }, /* 15 */ { UD_Ifcmovbe, O_ST0, O_ST5, O_NONE, P_none }, /* 16 */ { UD_Ifcmovbe, O_ST0, O_ST6, O_NONE, P_none }, /* 17 */ { UD_Ifcmovbe, O_ST0, O_ST7, O_NONE, P_none }, /* 18 */ { UD_Ifcmovu, O_ST0, O_ST0, O_NONE, P_none }, /* 19 */ { UD_Ifcmovu, O_ST0, O_ST1, O_NONE, P_none }, /* 1A */ { UD_Ifcmovu, O_ST0, O_ST2, O_NONE, P_none }, /* 1B */ { UD_Ifcmovu, O_ST0, O_ST3, O_NONE, P_none }, /* 1C */ { UD_Ifcmovu, O_ST0, O_ST4, O_NONE, P_none }, /* 1D */ { UD_Ifcmovu, O_ST0, O_ST5, O_NONE, P_none }, /* 1E */ { UD_Ifcmovu, O_ST0, O_ST6, O_NONE, P_none }, /* 1F */ { UD_Ifcmovu, O_ST0, O_ST7, O_NONE, P_none }, /* 20 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 21 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 22 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 23 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 24 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 25 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 26 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 27 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 28 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 29 */ { UD_Ifucompp, O_NONE, O_NONE, O_NONE, P_none }, /* 2A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 30 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 31 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 32 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 33 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 34 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 35 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 36 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 37 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 38 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 39 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__1byte__op_db__mod[2] = { /* 00 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DB__MOD__OP_00__REG }, /* 01 */ { UD_Igrp_x87, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DB__MOD__OP_01__X87 }, }; static struct ud_itab_entry itab__1byte__op_db__mod__op_00__reg[8] = { /* 00 */ { UD_Ifild, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Ifisttp, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ifist, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Ifistp, O_Md, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Ifld, O_Mt, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Ifstp, O_Mt, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__1byte__op_db__mod__op_01__x87[64] = { /* 00 */ { UD_Ifcmovnb, O_ST0, O_ST0, O_NONE, P_none }, /* 01 */ { UD_Ifcmovnb, O_ST0, O_ST1, O_NONE, P_none }, /* 02 */ { UD_Ifcmovnb, O_ST0, O_ST2, O_NONE, P_none }, /* 03 */ { UD_Ifcmovnb, O_ST0, O_ST3, O_NONE, P_none }, /* 04 */ { UD_Ifcmovnb, O_ST0, O_ST4, O_NONE, P_none }, /* 05 */ { UD_Ifcmovnb, O_ST0, O_ST5, O_NONE, P_none }, /* 06 */ { UD_Ifcmovnb, O_ST0, O_ST6, O_NONE, P_none }, /* 07 */ { UD_Ifcmovnb, O_ST0, O_ST7, O_NONE, P_none }, /* 08 */ { UD_Ifcmovne, O_ST0, O_ST0, O_NONE, P_none }, /* 09 */ { UD_Ifcmovne, O_ST0, O_ST1, O_NONE, P_none }, /* 0A */ { UD_Ifcmovne, O_ST0, O_ST2, O_NONE, P_none }, /* 0B */ { UD_Ifcmovne, O_ST0, O_ST3, O_NONE, P_none }, /* 0C */ { UD_Ifcmovne, O_ST0, O_ST4, O_NONE, P_none }, /* 0D */ { UD_Ifcmovne, O_ST0, O_ST5, O_NONE, P_none }, /* 0E */ { UD_Ifcmovne, O_ST0, O_ST6, O_NONE, P_none }, /* 0F */ { UD_Ifcmovne, O_ST0, O_ST7, O_NONE, P_none }, /* 10 */ { UD_Ifcmovnbe, O_ST0, O_ST0, O_NONE, P_none }, /* 11 */ { UD_Ifcmovnbe, O_ST0, O_ST1, O_NONE, P_none }, /* 12 */ { UD_Ifcmovnbe, O_ST0, O_ST2, O_NONE, P_none }, /* 13 */ { UD_Ifcmovnbe, O_ST0, O_ST3, O_NONE, P_none }, /* 14 */ { UD_Ifcmovnbe, O_ST0, O_ST4, O_NONE, P_none }, /* 15 */ { UD_Ifcmovnbe, O_ST0, O_ST5, O_NONE, P_none }, /* 16 */ { UD_Ifcmovnbe, O_ST0, O_ST6, O_NONE, P_none }, /* 17 */ { UD_Ifcmovnbe, O_ST0, O_ST7, O_NONE, P_none }, /* 18 */ { UD_Ifcmovnu, O_ST0, O_ST0, O_NONE, P_none }, /* 19 */ { UD_Ifcmovnu, O_ST0, O_ST1, O_NONE, P_none }, /* 1A */ { UD_Ifcmovnu, O_ST0, O_ST2, O_NONE, P_none }, /* 1B */ { UD_Ifcmovnu, O_ST0, O_ST3, O_NONE, P_none }, /* 1C */ { UD_Ifcmovnu, O_ST0, O_ST4, O_NONE, P_none }, /* 1D */ { UD_Ifcmovnu, O_ST0, O_ST5, O_NONE, P_none }, /* 1E */ { UD_Ifcmovnu, O_ST0, O_ST6, O_NONE, P_none }, /* 1F */ { UD_Ifcmovnu, O_ST0, O_ST7, O_NONE, P_none }, /* 20 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 21 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 22 */ { UD_Ifclex, O_NONE, O_NONE, O_NONE, P_none }, /* 23 */ { UD_Ifninit, O_NONE, O_NONE, O_NONE, P_none }, /* 24 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 25 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 26 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 27 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 28 */ { UD_Ifucomi, O_ST0, O_ST0, O_NONE, P_none }, /* 29 */ { UD_Ifucomi, O_ST0, O_ST1, O_NONE, P_none }, /* 2A */ { UD_Ifucomi, O_ST0, O_ST2, O_NONE, P_none }, /* 2B */ { UD_Ifucomi, O_ST0, O_ST3, O_NONE, P_none }, /* 2C */ { UD_Ifucomi, O_ST0, O_ST4, O_NONE, P_none }, /* 2D */ { UD_Ifucomi, O_ST0, O_ST5, O_NONE, P_none }, /* 2E */ { UD_Ifucomi, O_ST0, O_ST6, O_NONE, P_none }, /* 2F */ { UD_Ifucomi, O_ST0, O_ST7, O_NONE, P_none }, /* 30 */ { UD_Ifcomi, O_ST0, O_ST0, O_NONE, P_none }, /* 31 */ { UD_Ifcomi, O_ST0, O_ST1, O_NONE, P_none }, /* 32 */ { UD_Ifcomi, O_ST0, O_ST2, O_NONE, P_none }, /* 33 */ { UD_Ifcomi, O_ST0, O_ST3, O_NONE, P_none }, /* 34 */ { UD_Ifcomi, O_ST0, O_ST4, O_NONE, P_none }, /* 35 */ { UD_Ifcomi, O_ST0, O_ST5, O_NONE, P_none }, /* 36 */ { UD_Ifcomi, O_ST0, O_ST6, O_NONE, P_none }, /* 37 */ { UD_Ifcomi, O_ST0, O_ST7, O_NONE, P_none }, /* 38 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 39 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__1byte__op_dc__mod[2] = { /* 00 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DC__MOD__OP_00__REG }, /* 01 */ { UD_Igrp_x87, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DC__MOD__OP_01__X87 }, }; static struct ud_itab_entry itab__1byte__op_dc__mod__op_00__reg[8] = { /* 00 */ { UD_Ifadd, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Ifmul, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ifcom, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Ifcomp, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Ifsub, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 05 */ { UD_Ifsubr, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 06 */ { UD_Ifdiv, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 07 */ { UD_Ifdivr, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__1byte__op_dc__mod__op_01__x87[64] = { /* 00 */ { UD_Ifadd, O_ST0, O_ST0, O_NONE, P_none }, /* 01 */ { UD_Ifadd, O_ST1, O_ST0, O_NONE, P_none }, /* 02 */ { UD_Ifadd, O_ST2, O_ST0, O_NONE, P_none }, /* 03 */ { UD_Ifadd, O_ST3, O_ST0, O_NONE, P_none }, /* 04 */ { UD_Ifadd, O_ST4, O_ST0, O_NONE, P_none }, /* 05 */ { UD_Ifadd, O_ST5, O_ST0, O_NONE, P_none }, /* 06 */ { UD_Ifadd, O_ST6, O_ST0, O_NONE, P_none }, /* 07 */ { UD_Ifadd, O_ST7, O_ST0, O_NONE, P_none }, /* 08 */ { UD_Ifmul, O_ST0, O_ST0, O_NONE, P_none }, /* 09 */ { UD_Ifmul, O_ST1, O_ST0, O_NONE, P_none }, /* 0A */ { UD_Ifmul, O_ST2, O_ST0, O_NONE, P_none }, /* 0B */ { UD_Ifmul, O_ST3, O_ST0, O_NONE, P_none }, /* 0C */ { UD_Ifmul, O_ST4, O_ST0, O_NONE, P_none }, /* 0D */ { UD_Ifmul, O_ST5, O_ST0, O_NONE, P_none }, /* 0E */ { UD_Ifmul, O_ST6, O_ST0, O_NONE, P_none }, /* 0F */ { UD_Ifmul, O_ST7, O_ST0, O_NONE, P_none }, /* 10 */ { UD_Ifcom2, O_ST0, O_NONE, O_NONE, P_none }, /* 11 */ { UD_Ifcom2, O_ST1, O_NONE, O_NONE, P_none }, /* 12 */ { UD_Ifcom2, O_ST2, O_NONE, O_NONE, P_none }, /* 13 */ { UD_Ifcom2, O_ST3, O_NONE, O_NONE, P_none }, /* 14 */ { UD_Ifcom2, O_ST4, O_NONE, O_NONE, P_none }, /* 15 */ { UD_Ifcom2, O_ST5, O_NONE, O_NONE, P_none }, /* 16 */ { UD_Ifcom2, O_ST6, O_NONE, O_NONE, P_none }, /* 17 */ { UD_Ifcom2, O_ST7, O_NONE, O_NONE, P_none }, /* 18 */ { UD_Ifcomp3, O_ST0, O_NONE, O_NONE, P_none }, /* 19 */ { UD_Ifcomp3, O_ST1, O_NONE, O_NONE, P_none }, /* 1A */ { UD_Ifcomp3, O_ST2, O_NONE, O_NONE, P_none }, /* 1B */ { UD_Ifcomp3, O_ST3, O_NONE, O_NONE, P_none }, /* 1C */ { UD_Ifcomp3, O_ST4, O_NONE, O_NONE, P_none }, /* 1D */ { UD_Ifcomp3, O_ST5, O_NONE, O_NONE, P_none }, /* 1E */ { UD_Ifcomp3, O_ST6, O_NONE, O_NONE, P_none }, /* 1F */ { UD_Ifcomp3, O_ST7, O_NONE, O_NONE, P_none }, /* 20 */ { UD_Ifsubr, O_ST0, O_ST0, O_NONE, P_none }, /* 21 */ { UD_Ifsubr, O_ST1, O_ST0, O_NONE, P_none }, /* 22 */ { UD_Ifsubr, O_ST2, O_ST0, O_NONE, P_none }, /* 23 */ { UD_Ifsubr, O_ST3, O_ST0, O_NONE, P_none }, /* 24 */ { UD_Ifsubr, O_ST4, O_ST0, O_NONE, P_none }, /* 25 */ { UD_Ifsubr, O_ST5, O_ST0, O_NONE, P_none }, /* 26 */ { UD_Ifsubr, O_ST6, O_ST0, O_NONE, P_none }, /* 27 */ { UD_Ifsubr, O_ST7, O_ST0, O_NONE, P_none }, /* 28 */ { UD_Ifsub, O_ST0, O_ST0, O_NONE, P_none }, /* 29 */ { UD_Ifsub, O_ST1, O_ST0, O_NONE, P_none }, /* 2A */ { UD_Ifsub, O_ST2, O_ST0, O_NONE, P_none }, /* 2B */ { UD_Ifsub, O_ST3, O_ST0, O_NONE, P_none }, /* 2C */ { UD_Ifsub, O_ST4, O_ST0, O_NONE, P_none }, /* 2D */ { UD_Ifsub, O_ST5, O_ST0, O_NONE, P_none }, /* 2E */ { UD_Ifsub, O_ST6, O_ST0, O_NONE, P_none }, /* 2F */ { UD_Ifsub, O_ST7, O_ST0, O_NONE, P_none }, /* 30 */ { UD_Ifdivr, O_ST0, O_ST0, O_NONE, P_none }, /* 31 */ { UD_Ifdivr, O_ST1, O_ST0, O_NONE, P_none }, /* 32 */ { UD_Ifdivr, O_ST2, O_ST0, O_NONE, P_none }, /* 33 */ { UD_Ifdivr, O_ST3, O_ST0, O_NONE, P_none }, /* 34 */ { UD_Ifdivr, O_ST4, O_ST0, O_NONE, P_none }, /* 35 */ { UD_Ifdivr, O_ST5, O_ST0, O_NONE, P_none }, /* 36 */ { UD_Ifdivr, O_ST6, O_ST0, O_NONE, P_none }, /* 37 */ { UD_Ifdivr, O_ST7, O_ST0, O_NONE, P_none }, /* 38 */ { UD_Ifdiv, O_ST0, O_ST0, O_NONE, P_none }, /* 39 */ { UD_Ifdiv, O_ST1, O_ST0, O_NONE, P_none }, /* 3A */ { UD_Ifdiv, O_ST2, O_ST0, O_NONE, P_none }, /* 3B */ { UD_Ifdiv, O_ST3, O_ST0, O_NONE, P_none }, /* 3C */ { UD_Ifdiv, O_ST4, O_ST0, O_NONE, P_none }, /* 3D */ { UD_Ifdiv, O_ST5, O_ST0, O_NONE, P_none }, /* 3E */ { UD_Ifdiv, O_ST6, O_ST0, O_NONE, P_none }, /* 3F */ { UD_Ifdiv, O_ST7, O_ST0, O_NONE, P_none }, }; static struct ud_itab_entry itab__1byte__op_dd__mod[2] = { /* 00 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DD__MOD__OP_00__REG }, /* 01 */ { UD_Igrp_x87, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DD__MOD__OP_01__X87 }, }; static struct ud_itab_entry itab__1byte__op_dd__mod__op_00__reg[8] = { /* 00 */ { UD_Ifld, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Ifisttp, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ifst, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Ifstp, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Ifrstor, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Ifnsave, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 07 */ { UD_Ifnstsw, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__1byte__op_dd__mod__op_01__x87[64] = { /* 00 */ { UD_Iffree, O_ST0, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iffree, O_ST1, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Iffree, O_ST2, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Iffree, O_ST3, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Iffree, O_ST4, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iffree, O_ST5, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Iffree, O_ST6, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Iffree, O_ST7, O_NONE, O_NONE, P_none }, /* 08 */ { UD_Ifxch4, O_ST0, O_NONE, O_NONE, P_none }, /* 09 */ { UD_Ifxch4, O_ST1, O_NONE, O_NONE, P_none }, /* 0A */ { UD_Ifxch4, O_ST2, O_NONE, O_NONE, P_none }, /* 0B */ { UD_Ifxch4, O_ST3, O_NONE, O_NONE, P_none }, /* 0C */ { UD_Ifxch4, O_ST4, O_NONE, O_NONE, P_none }, /* 0D */ { UD_Ifxch4, O_ST5, O_NONE, O_NONE, P_none }, /* 0E */ { UD_Ifxch4, O_ST6, O_NONE, O_NONE, P_none }, /* 0F */ { UD_Ifxch4, O_ST7, O_NONE, O_NONE, P_none }, /* 10 */ { UD_Ifst, O_ST0, O_NONE, O_NONE, P_none }, /* 11 */ { UD_Ifst, O_ST1, O_NONE, O_NONE, P_none }, /* 12 */ { UD_Ifst, O_ST2, O_NONE, O_NONE, P_none }, /* 13 */ { UD_Ifst, O_ST3, O_NONE, O_NONE, P_none }, /* 14 */ { UD_Ifst, O_ST4, O_NONE, O_NONE, P_none }, /* 15 */ { UD_Ifst, O_ST5, O_NONE, O_NONE, P_none }, /* 16 */ { UD_Ifst, O_ST6, O_NONE, O_NONE, P_none }, /* 17 */ { UD_Ifst, O_ST7, O_NONE, O_NONE, P_none }, /* 18 */ { UD_Ifstp, O_ST0, O_NONE, O_NONE, P_none }, /* 19 */ { UD_Ifstp, O_ST1, O_NONE, O_NONE, P_none }, /* 1A */ { UD_Ifstp, O_ST2, O_NONE, O_NONE, P_none }, /* 1B */ { UD_Ifstp, O_ST3, O_NONE, O_NONE, P_none }, /* 1C */ { UD_Ifstp, O_ST4, O_NONE, O_NONE, P_none }, /* 1D */ { UD_Ifstp, O_ST5, O_NONE, O_NONE, P_none }, /* 1E */ { UD_Ifstp, O_ST6, O_NONE, O_NONE, P_none }, /* 1F */ { UD_Ifstp, O_ST7, O_NONE, O_NONE, P_none }, /* 20 */ { UD_Ifucom, O_ST0, O_NONE, O_NONE, P_none }, /* 21 */ { UD_Ifucom, O_ST1, O_NONE, O_NONE, P_none }, /* 22 */ { UD_Ifucom, O_ST2, O_NONE, O_NONE, P_none }, /* 23 */ { UD_Ifucom, O_ST3, O_NONE, O_NONE, P_none }, /* 24 */ { UD_Ifucom, O_ST4, O_NONE, O_NONE, P_none }, /* 25 */ { UD_Ifucom, O_ST5, O_NONE, O_NONE, P_none }, /* 26 */ { UD_Ifucom, O_ST6, O_NONE, O_NONE, P_none }, /* 27 */ { UD_Ifucom, O_ST7, O_NONE, O_NONE, P_none }, /* 28 */ { UD_Ifucomp, O_ST0, O_NONE, O_NONE, P_none }, /* 29 */ { UD_Ifucomp, O_ST1, O_NONE, O_NONE, P_none }, /* 2A */ { UD_Ifucomp, O_ST2, O_NONE, O_NONE, P_none }, /* 2B */ { UD_Ifucomp, O_ST3, O_NONE, O_NONE, P_none }, /* 2C */ { UD_Ifucomp, O_ST4, O_NONE, O_NONE, P_none }, /* 2D */ { UD_Ifucomp, O_ST5, O_NONE, O_NONE, P_none }, /* 2E */ { UD_Ifucomp, O_ST6, O_NONE, O_NONE, P_none }, /* 2F */ { UD_Ifucomp, O_ST7, O_NONE, O_NONE, P_none }, /* 30 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 31 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 32 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 33 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 34 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 35 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 36 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 37 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 38 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 39 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__1byte__op_de__mod[2] = { /* 00 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DE__MOD__OP_00__REG }, /* 01 */ { UD_Igrp_x87, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DE__MOD__OP_01__X87 }, }; static struct ud_itab_entry itab__1byte__op_de__mod__op_00__reg[8] = { /* 00 */ { UD_Ifiadd, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Ifimul, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ificom, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Ificomp, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Ifisub, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 05 */ { UD_Ifisubr, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 06 */ { UD_Ifidiv, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 07 */ { UD_Ifidivr, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__1byte__op_de__mod__op_01__x87[64] = { /* 00 */ { UD_Ifaddp, O_ST0, O_ST0, O_NONE, P_none }, /* 01 */ { UD_Ifaddp, O_ST1, O_ST0, O_NONE, P_none }, /* 02 */ { UD_Ifaddp, O_ST2, O_ST0, O_NONE, P_none }, /* 03 */ { UD_Ifaddp, O_ST3, O_ST0, O_NONE, P_none }, /* 04 */ { UD_Ifaddp, O_ST4, O_ST0, O_NONE, P_none }, /* 05 */ { UD_Ifaddp, O_ST5, O_ST0, O_NONE, P_none }, /* 06 */ { UD_Ifaddp, O_ST6, O_ST0, O_NONE, P_none }, /* 07 */ { UD_Ifaddp, O_ST7, O_ST0, O_NONE, P_none }, /* 08 */ { UD_Ifmulp, O_ST0, O_ST0, O_NONE, P_none }, /* 09 */ { UD_Ifmulp, O_ST1, O_ST0, O_NONE, P_none }, /* 0A */ { UD_Ifmulp, O_ST2, O_ST0, O_NONE, P_none }, /* 0B */ { UD_Ifmulp, O_ST3, O_ST0, O_NONE, P_none }, /* 0C */ { UD_Ifmulp, O_ST4, O_ST0, O_NONE, P_none }, /* 0D */ { UD_Ifmulp, O_ST5, O_ST0, O_NONE, P_none }, /* 0E */ { UD_Ifmulp, O_ST6, O_ST0, O_NONE, P_none }, /* 0F */ { UD_Ifmulp, O_ST7, O_ST0, O_NONE, P_none }, /* 10 */ { UD_Ifcomp5, O_ST0, O_NONE, O_NONE, P_none }, /* 11 */ { UD_Ifcomp5, O_ST1, O_NONE, O_NONE, P_none }, /* 12 */ { UD_Ifcomp5, O_ST2, O_NONE, O_NONE, P_none }, /* 13 */ { UD_Ifcomp5, O_ST3, O_NONE, O_NONE, P_none }, /* 14 */ { UD_Ifcomp5, O_ST4, O_NONE, O_NONE, P_none }, /* 15 */ { UD_Ifcomp5, O_ST5, O_NONE, O_NONE, P_none }, /* 16 */ { UD_Ifcomp5, O_ST6, O_NONE, O_NONE, P_none }, /* 17 */ { UD_Ifcomp5, O_ST7, O_NONE, O_NONE, P_none }, /* 18 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 19 */ { UD_Ifcompp, O_NONE, O_NONE, O_NONE, P_none }, /* 1A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 20 */ { UD_Ifsubrp, O_ST0, O_ST0, O_NONE, P_none }, /* 21 */ { UD_Ifsubrp, O_ST1, O_ST0, O_NONE, P_none }, /* 22 */ { UD_Ifsubrp, O_ST2, O_ST0, O_NONE, P_none }, /* 23 */ { UD_Ifsubrp, O_ST3, O_ST0, O_NONE, P_none }, /* 24 */ { UD_Ifsubrp, O_ST4, O_ST0, O_NONE, P_none }, /* 25 */ { UD_Ifsubrp, O_ST5, O_ST0, O_NONE, P_none }, /* 26 */ { UD_Ifsubrp, O_ST6, O_ST0, O_NONE, P_none }, /* 27 */ { UD_Ifsubrp, O_ST7, O_ST0, O_NONE, P_none }, /* 28 */ { UD_Ifsubp, O_ST0, O_ST0, O_NONE, P_none }, /* 29 */ { UD_Ifsubp, O_ST1, O_ST0, O_NONE, P_none }, /* 2A */ { UD_Ifsubp, O_ST2, O_ST0, O_NONE, P_none }, /* 2B */ { UD_Ifsubp, O_ST3, O_ST0, O_NONE, P_none }, /* 2C */ { UD_Ifsubp, O_ST4, O_ST0, O_NONE, P_none }, /* 2D */ { UD_Ifsubp, O_ST5, O_ST0, O_NONE, P_none }, /* 2E */ { UD_Ifsubp, O_ST6, O_ST0, O_NONE, P_none }, /* 2F */ { UD_Ifsubp, O_ST7, O_ST0, O_NONE, P_none }, /* 30 */ { UD_Ifdivrp, O_ST0, O_ST0, O_NONE, P_none }, /* 31 */ { UD_Ifdivrp, O_ST1, O_ST0, O_NONE, P_none }, /* 32 */ { UD_Ifdivrp, O_ST2, O_ST0, O_NONE, P_none }, /* 33 */ { UD_Ifdivrp, O_ST3, O_ST0, O_NONE, P_none }, /* 34 */ { UD_Ifdivrp, O_ST4, O_ST0, O_NONE, P_none }, /* 35 */ { UD_Ifdivrp, O_ST5, O_ST0, O_NONE, P_none }, /* 36 */ { UD_Ifdivrp, O_ST6, O_ST0, O_NONE, P_none }, /* 37 */ { UD_Ifdivrp, O_ST7, O_ST0, O_NONE, P_none }, /* 38 */ { UD_Ifdivp, O_ST0, O_ST0, O_NONE, P_none }, /* 39 */ { UD_Ifdivp, O_ST1, O_ST0, O_NONE, P_none }, /* 3A */ { UD_Ifdivp, O_ST2, O_ST0, O_NONE, P_none }, /* 3B */ { UD_Ifdivp, O_ST3, O_ST0, O_NONE, P_none }, /* 3C */ { UD_Ifdivp, O_ST4, O_ST0, O_NONE, P_none }, /* 3D */ { UD_Ifdivp, O_ST5, O_ST0, O_NONE, P_none }, /* 3E */ { UD_Ifdivp, O_ST6, O_ST0, O_NONE, P_none }, /* 3F */ { UD_Ifdivp, O_ST7, O_ST0, O_NONE, P_none }, }; static struct ud_itab_entry itab__1byte__op_df__mod[2] = { /* 00 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DF__MOD__OP_00__REG }, /* 01 */ { UD_Igrp_x87, O_NONE, O_NONE, O_NONE, ITAB__1BYTE__OP_DF__MOD__OP_01__X87 }, }; static struct ud_itab_entry itab__1byte__op_df__mod__op_00__reg[8] = { /* 00 */ { UD_Ifild, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Ifisttp, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ifist, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Ifistp, O_Mw, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Ifbld, O_Mt, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 05 */ { UD_Ifild, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 06 */ { UD_Ifbstp, O_Mt, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 07 */ { UD_Ifistp, O_Mq, O_NONE, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__1byte__op_df__mod__op_01__x87[64] = { /* 00 */ { UD_Iffreep, O_ST0, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iffreep, O_ST1, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Iffreep, O_ST2, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Iffreep, O_ST3, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Iffreep, O_ST4, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iffreep, O_ST5, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Iffreep, O_ST6, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Iffreep, O_ST7, O_NONE, O_NONE, P_none }, /* 08 */ { UD_Ifxch7, O_ST0, O_NONE, O_NONE, P_none }, /* 09 */ { UD_Ifxch7, O_ST1, O_NONE, O_NONE, P_none }, /* 0A */ { UD_Ifxch7, O_ST2, O_NONE, O_NONE, P_none }, /* 0B */ { UD_Ifxch7, O_ST3, O_NONE, O_NONE, P_none }, /* 0C */ { UD_Ifxch7, O_ST4, O_NONE, O_NONE, P_none }, /* 0D */ { UD_Ifxch7, O_ST5, O_NONE, O_NONE, P_none }, /* 0E */ { UD_Ifxch7, O_ST6, O_NONE, O_NONE, P_none }, /* 0F */ { UD_Ifxch7, O_ST7, O_NONE, O_NONE, P_none }, /* 10 */ { UD_Ifstp8, O_ST0, O_NONE, O_NONE, P_none }, /* 11 */ { UD_Ifstp8, O_ST1, O_NONE, O_NONE, P_none }, /* 12 */ { UD_Ifstp8, O_ST2, O_NONE, O_NONE, P_none }, /* 13 */ { UD_Ifstp8, O_ST3, O_NONE, O_NONE, P_none }, /* 14 */ { UD_Ifstp8, O_ST4, O_NONE, O_NONE, P_none }, /* 15 */ { UD_Ifstp8, O_ST5, O_NONE, O_NONE, P_none }, /* 16 */ { UD_Ifstp8, O_ST6, O_NONE, O_NONE, P_none }, /* 17 */ { UD_Ifstp8, O_ST7, O_NONE, O_NONE, P_none }, /* 18 */ { UD_Ifstp9, O_ST0, O_NONE, O_NONE, P_none }, /* 19 */ { UD_Ifstp9, O_ST1, O_NONE, O_NONE, P_none }, /* 1A */ { UD_Ifstp9, O_ST2, O_NONE, O_NONE, P_none }, /* 1B */ { UD_Ifstp9, O_ST3, O_NONE, O_NONE, P_none }, /* 1C */ { UD_Ifstp9, O_ST4, O_NONE, O_NONE, P_none }, /* 1D */ { UD_Ifstp9, O_ST5, O_NONE, O_NONE, P_none }, /* 1E */ { UD_Ifstp9, O_ST6, O_NONE, O_NONE, P_none }, /* 1F */ { UD_Ifstp9, O_ST7, O_NONE, O_NONE, P_none }, /* 20 */ { UD_Ifnstsw, O_AX, O_NONE, O_NONE, P_none }, /* 21 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 22 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 23 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 24 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 25 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 26 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 27 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 28 */ { UD_Ifucomip, O_ST0, O_ST0, O_NONE, P_none }, /* 29 */ { UD_Ifucomip, O_ST0, O_ST1, O_NONE, P_none }, /* 2A */ { UD_Ifucomip, O_ST0, O_ST2, O_NONE, P_none }, /* 2B */ { UD_Ifucomip, O_ST0, O_ST3, O_NONE, P_none }, /* 2C */ { UD_Ifucomip, O_ST0, O_ST4, O_NONE, P_none }, /* 2D */ { UD_Ifucomip, O_ST0, O_ST5, O_NONE, P_none }, /* 2E */ { UD_Ifucomip, O_ST0, O_ST6, O_NONE, P_none }, /* 2F */ { UD_Ifucomip, O_ST0, O_ST7, O_NONE, P_none }, /* 30 */ { UD_Ifcomip, O_ST0, O_ST0, O_NONE, P_none }, /* 31 */ { UD_Ifcomip, O_ST0, O_ST1, O_NONE, P_none }, /* 32 */ { UD_Ifcomip, O_ST0, O_ST2, O_NONE, P_none }, /* 33 */ { UD_Ifcomip, O_ST0, O_ST3, O_NONE, P_none }, /* 34 */ { UD_Ifcomip, O_ST0, O_ST4, O_NONE, P_none }, /* 35 */ { UD_Ifcomip, O_ST0, O_ST5, O_NONE, P_none }, /* 36 */ { UD_Ifcomip, O_ST0, O_ST6, O_NONE, P_none }, /* 37 */ { UD_Ifcomip, O_ST0, O_ST7, O_NONE, P_none }, /* 38 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 39 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__1byte__op_e3__asize[3] = { /* 00 */ { UD_Ijcxz, O_Jb, O_NONE, O_NONE, P_aso }, /* 01 */ { UD_Ijecxz, O_Jb, O_NONE, O_NONE, P_aso }, /* 02 */ { UD_Ijrcxz, O_Jb, O_NONE, O_NONE, P_aso }, }; static struct ud_itab_entry itab__1byte__op_f6__reg[8] = { /* 00 */ { UD_Itest, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Itest, O_Eb, O_Ib, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Inot, O_Eb, O_NONE, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Ineg, O_Eb, O_NONE, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Imul, O_Eb, O_NONE, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 05 */ { UD_Iimul, O_Eb, O_NONE, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 06 */ { UD_Idiv, O_Eb, O_NONE, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 07 */ { UD_Iidiv, O_Eb, O_NONE, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__1byte__op_f7__reg[8] = { /* 00 */ { UD_Itest, O_Ev, O_Iz, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Itest, O_Ev, O_Iz, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Inot, O_Ev, O_NONE, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Ineg, O_Ev, O_NONE, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Imul, O_Ev, O_NONE, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 05 */ { UD_Iimul, O_Ev, O_NONE, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 06 */ { UD_Idiv, O_Ev, O_NONE, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 07 */ { UD_Iidiv, O_Ev, O_NONE, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__1byte__op_fe__reg[8] = { /* 00 */ { UD_Iinc, O_Eb, O_NONE, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Idec, O_Eb, O_NONE, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__1byte__op_ff__reg[8] = { /* 00 */ { UD_Iinc, O_Ev, O_NONE, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 01 */ { UD_Idec, O_Ev, O_NONE, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Icall, O_Ev, O_NONE, O_NONE, P_c1|P_def64|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 03 */ { UD_Icall, O_Ep, O_NONE, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 04 */ { UD_Ijmp, O_Ev, O_NONE, O_NONE, P_c1|P_def64|P_depM|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 05 */ { UD_Ijmp, O_Ep, O_NONE, O_NONE, P_c1|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 06 */ { UD_Ipush, O_Ev, O_NONE, O_NONE, P_c1|P_def64|P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__3dnow[256] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 08 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 09 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 10 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 11 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 12 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 13 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 14 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 15 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 16 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 17 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 18 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 19 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 20 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 21 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 22 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 23 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 24 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 25 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 26 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 27 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 28 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 29 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 30 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 31 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 32 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 33 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 34 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 35 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 36 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 37 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 38 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 39 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 40 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 41 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 42 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 43 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 44 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 45 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 46 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 47 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 48 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 49 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 50 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 51 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 52 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 53 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 54 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 55 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 56 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 57 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 58 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 59 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 5A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 5B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 5C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 5D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 5E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 5F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 60 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 61 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 62 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 63 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 64 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 65 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 66 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 67 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 68 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 69 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 70 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 71 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 72 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 73 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 74 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 75 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 76 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 77 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 78 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 79 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 80 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 81 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 82 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 83 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 84 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 85 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 86 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 87 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 88 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 89 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 90 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 91 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 92 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 93 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 94 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 95 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 96 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 97 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 98 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 99 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* EA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* EB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* EC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* ED */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* EE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* EF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__pfx_sse66__0f[256] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 08 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 09 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 10 */ { UD_Imovupd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 11 */ { UD_Imovupd, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 12 */ { UD_Imovlpd, O_V, O_M, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 13 */ { UD_Imovlpd, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 14 */ { UD_Iunpcklpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 15 */ { UD_Iunpckhpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 16 */ { UD_Imovhpd, O_V, O_M, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 17 */ { UD_Imovhpd, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 18 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 19 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 20 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 21 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 22 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 23 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 24 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 25 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 26 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 27 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 28 */ { UD_Imovapd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 29 */ { UD_Imovapd, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 2A */ { UD_Icvtpi2pd, O_V, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 2B */ { UD_Imovntpd, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 2C */ { UD_Icvttpd2pi, O_P, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 2D */ { UD_Icvtpd2pi, O_P, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 2E */ { UD_Iucomisd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 2F */ { UD_Icomisd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 30 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 31 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 32 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 33 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 34 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 35 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 36 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 37 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 38 */ { UD_Igrp_3byte, O_NONE, O_NONE, O_NONE, ITAB__PFX_SSE66__0F__38 }, /* 39 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 40 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 41 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 42 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 43 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 44 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 45 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 46 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 47 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 48 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 49 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 50 */ { UD_Imovmskpd, O_Gd, O_VR, O_NONE, P_oso|P_rexr|P_rexb }, /* 51 */ { UD_Isqrtpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 52 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 53 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 54 */ { UD_Iandpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 55 */ { UD_Iandnpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 56 */ { UD_Iorpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 57 */ { UD_Ixorpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 58 */ { UD_Iaddpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 59 */ { UD_Imulpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 5A */ { UD_Icvtpd2ps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 5B */ { UD_Icvtps2dq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 5C */ { UD_Isubpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 5D */ { UD_Iminpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 5E */ { UD_Idivpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 5F */ { UD_Imaxpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 60 */ { UD_Ipunpcklbw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 61 */ { UD_Ipunpcklwd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 62 */ { UD_Ipunpckldq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 63 */ { UD_Ipacksswb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 64 */ { UD_Ipcmpgtb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 65 */ { UD_Ipcmpgtw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 66 */ { UD_Ipcmpgtd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 67 */ { UD_Ipackuswb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 68 */ { UD_Ipunpckhbw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 69 */ { UD_Ipunpckhwd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 6A */ { UD_Ipunpckhdq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 6B */ { UD_Ipackssdw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 6C */ { UD_Ipunpcklqdq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 6D */ { UD_Ipunpckhqdq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 6E */ { UD_Imovd, O_V, O_Ex, O_NONE, P_c2|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 6F */ { UD_Imovqa, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 70 */ { UD_Ipshufd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 71 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__PFX_SSE66__0F__OP_71__REG }, /* 72 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__PFX_SSE66__0F__OP_72__REG }, /* 73 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__PFX_SSE66__0F__OP_73__REG }, /* 74 */ { UD_Ipcmpeqb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 75 */ { UD_Ipcmpeqw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 76 */ { UD_Ipcmpeqd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 77 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 78 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 79 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7C */ { UD_Ihaddpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 7D */ { UD_Ihsubpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 7E */ { UD_Imovd, O_Ex, O_V, O_NONE, P_c1|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 7F */ { UD_Imovdqa, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 80 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 81 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 82 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 83 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 84 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 85 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 86 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 87 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 88 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 89 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 90 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 91 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 92 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 93 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 94 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 95 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 96 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 97 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 98 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 99 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C0 */ { UD_Ixadd, O_Eb, O_Gb, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* C1 */ { UD_Ixadd, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* C2 */ { UD_Icmppd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* C3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C4 */ { UD_Ipinsrw, O_V, O_Ew, O_Ib, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* C5 */ { UD_Ipextrw, O_Gd, O_VR, O_Ib, P_aso|P_rexr|P_rexb }, /* C6 */ { UD_Ishufpd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* C7 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__PFX_SSE66__0F__OP_C7__REG }, /* C8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D0 */ { UD_Iaddsubpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* D1 */ { UD_Ipsrlw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* D2 */ { UD_Ipsrld, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* D3 */ { UD_Ipsrlq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* D4 */ { UD_Ipaddq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* D5 */ { UD_Ipmullw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* D6 */ { UD_Imovq, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* D7 */ { UD_Ipmovmskb, O_Gd, O_VR, O_NONE, P_rexr|P_rexb }, /* D8 */ { UD_Ipsubusb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* D9 */ { UD_Ipsubusw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* DA */ { UD_Ipminub, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* DB */ { UD_Ipand, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* DC */ { UD_Ipsubusb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* DD */ { UD_Ipunpckhbw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* DE */ { UD_Ipmaxub, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* DF */ { UD_Ipandn, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* E0 */ { UD_Ipavgb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* E1 */ { UD_Ipsraw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* E2 */ { UD_Ipsrad, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* E3 */ { UD_Ipavgw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* E4 */ { UD_Ipmulhuw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* E5 */ { UD_Ipmulhw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* E6 */ { UD_Icvttpd2dq, O_V, O_W, O_NONE, P_none }, /* E7 */ { UD_Imovntdq, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* E8 */ { UD_Ipsubsb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* E9 */ { UD_Ipsubsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* EA */ { UD_Ipminsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* EB */ { UD_Ipor, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* EC */ { UD_Ipaddsb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* ED */ { UD_Ipaddsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* EE */ { UD_Ipmaxsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* EF */ { UD_Ipxor, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* F0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F1 */ { UD_Ipsllw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* F2 */ { UD_Ipslld, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* F3 */ { UD_Ipsllq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* F4 */ { UD_Ipmuludq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* F5 */ { UD_Ipmaddwd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* F6 */ { UD_Ipsadbw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* F7 */ { UD_Imaskmovq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* F8 */ { UD_Ipsubb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* F9 */ { UD_Ipsubw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* FA */ { UD_Ipsubd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* FB */ { UD_Ipsubq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* FC */ { UD_Ipaddb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* FD */ { UD_Ipaddw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* FE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__pfx_sse66__0f__38[256] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 08 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 09 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 10 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 11 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 12 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 13 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 14 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 15 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 16 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 17 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 18 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 19 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 20 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 21 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 22 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 23 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 24 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 25 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 26 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 27 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 28 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 29 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 30 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 31 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 32 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 33 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 34 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 35 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 36 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 37 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 38 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 39 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 40 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 41 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 42 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 43 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 44 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 45 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 46 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 47 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 48 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 49 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 50 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 51 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 52 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 53 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 54 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 55 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 56 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 57 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 58 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 59 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 5A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 5B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 5C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 5D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 5E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 5F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 60 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 61 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 62 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 63 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 64 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 65 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 66 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 67 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 68 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 69 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 70 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 71 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 72 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 73 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 74 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 75 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 76 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 77 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 78 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 79 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 80 */ { UD_Igrp_mode, O_NONE, O_NONE, O_NONE, ITAB__PFX_SSE66__0F__38__OP_80__MODE }, /* 81 */ { UD_Igrp_mode, O_NONE, O_NONE, O_NONE, ITAB__PFX_SSE66__0F__38__OP_81__MODE }, /* 82 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 83 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 84 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 85 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 86 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 87 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 88 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 89 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 90 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 91 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 92 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 93 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 94 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 95 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 96 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 97 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 98 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 99 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* EA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* EB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* EC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* ED */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* EE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* EF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__pfx_sse66__0f__38__op_80__mode[3] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__PFX_SSE66__0F__38__OP_80__MODE__OP_01__VENDOR }, /* 02 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__PFX_SSE66__0F__38__OP_80__MODE__OP_02__VENDOR }, }; static struct ud_itab_entry itab__pfx_sse66__0f__38__op_80__mode__op_01__vendor[3] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvept, O_Gd, O_Mo, O_NONE, P_none }, /* 02 */ { UD_Iinvept, O_Gd, O_Mo, O_NONE, P_none }, }; static struct ud_itab_entry itab__pfx_sse66__0f__38__op_80__mode__op_02__vendor[3] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvept, O_Gq, O_Mo, O_NONE, P_none }, /* 02 */ { UD_Iinvept, O_Gq, O_Mo, O_NONE, P_none }, }; static struct ud_itab_entry itab__pfx_sse66__0f__38__op_81__mode[3] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__PFX_SSE66__0F__38__OP_81__MODE__OP_01__VENDOR }, /* 02 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__PFX_SSE66__0F__38__OP_81__MODE__OP_02__VENDOR }, }; static struct ud_itab_entry itab__pfx_sse66__0f__38__op_81__mode__op_01__vendor[3] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvvpid, O_Gd, O_Mo, O_NONE, P_none }, /* 02 */ { UD_Iinvvpid, O_Gd, O_Mo, O_NONE, P_none }, }; static struct ud_itab_entry itab__pfx_sse66__0f__38__op_81__mode__op_02__vendor[3] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvvpid, O_Gq, O_Mo, O_NONE, P_none }, /* 02 */ { UD_Iinvvpid, O_Gq, O_Mo, O_NONE, P_none }, }; static struct ud_itab_entry itab__pfx_sse66__0f__op_71__reg[8] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Ipsrlw, O_VR, O_Ib, O_NONE, P_rexb }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Ipsraw, O_VR, O_Ib, O_NONE, P_rexb }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Ipsllw, O_VR, O_Ib, O_NONE, P_rexb }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__pfx_sse66__0f__op_72__reg[8] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Ipsrld, O_VR, O_Ib, O_NONE, P_rexb }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Ipsrad, O_VR, O_Ib, O_NONE, P_rexb }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Ipslld, O_VR, O_Ib, O_NONE, P_rexb }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__pfx_sse66__0f__op_73__reg[8] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Ipsrlq, O_VR, O_Ib, O_NONE, P_rexb }, /* 03 */ { UD_Ipsrldq, O_VR, O_Ib, O_NONE, P_rexb }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Ipsllq, O_VR, O_Ib, O_NONE, P_rexb }, /* 07 */ { UD_Ipslldq, O_VR, O_Ib, O_NONE, P_rexb }, }; static struct ud_itab_entry itab__pfx_sse66__0f__op_c7__reg[8] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__PFX_SSE66__0F__OP_C7__REG__OP_06__VENDOR }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__pfx_sse66__0f__op_c7__reg__op_06__vendor[3] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Ivmclear, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ivmclear, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, }; static struct ud_itab_entry itab__pfx_ssef2__0f[256] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 08 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 09 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 10 */ { UD_Imovsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 11 */ { UD_Imovsd, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 12 */ { UD_Imovddup, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 13 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 14 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 15 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 16 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 17 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 18 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 19 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 20 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 21 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 22 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 23 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 24 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 25 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 26 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 27 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 28 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 29 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2A */ { UD_Icvtsi2sd, O_V, O_Ex, O_NONE, P_c2|P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 2B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2C */ { UD_Icvttsd2si, O_Gvw, O_W, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 2D */ { UD_Icvtsd2si, O_Gvw, O_W, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 2E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 30 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 31 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 32 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 33 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 34 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 35 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 36 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 37 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 38 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 39 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 40 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 41 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 42 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 43 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 44 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 45 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 46 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 47 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 48 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 49 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 50 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 51 */ { UD_Isqrtsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 52 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 53 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 54 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 55 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 56 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 57 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 58 */ { UD_Iaddsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 59 */ { UD_Imulsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 5A */ { UD_Icvtsd2ss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 5B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 5C */ { UD_Isubsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 5D */ { UD_Iminsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 5E */ { UD_Idivsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 5F */ { UD_Imaxsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 60 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 61 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 62 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 63 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 64 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 65 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 66 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 67 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 68 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 69 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 70 */ { UD_Ipshuflw, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 71 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 72 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 73 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 74 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 75 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 76 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 77 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 78 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 79 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7C */ { UD_Ihaddps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 7D */ { UD_Ihsubps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 7E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 80 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 81 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 82 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 83 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 84 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 85 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 86 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 87 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 88 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 89 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 90 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 91 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 92 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 93 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 94 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 95 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 96 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 97 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 98 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 99 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C0 */ { UD_Ixadd, O_Eb, O_Gb, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* C1 */ { UD_Ixadd, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexr|P_rexx|P_rexb }, /* C2 */ { UD_Icmpsd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* C3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D0 */ { UD_Iaddsubps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* D1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D6 */ { UD_Imovdq2q, O_P, O_VR, O_NONE, P_aso|P_rexb }, /* D7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E6 */ { UD_Icvtpd2dq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* E7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* EA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* EB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* EC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* ED */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* EE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* EF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F0 */ { UD_Ilddqu, O_V, O_M, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* F1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__pfx_ssef3__0f[256] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 08 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 09 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 10 */ { UD_Imovss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 11 */ { UD_Imovss, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 12 */ { UD_Imovsldup, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 13 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 14 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 15 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 16 */ { UD_Imovshdup, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 17 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 18 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 19 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 1F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 20 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 21 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 22 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 23 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 24 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 25 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 26 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 27 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 28 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 29 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2A */ { UD_Icvtsi2ss, O_V, O_Ex, O_NONE, P_c2|P_aso|P_rexr|P_rexx|P_rexb }, /* 2B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2C */ { UD_Icvttss2si, O_Gvw, O_W, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 2D */ { UD_Icvtss2si, O_Gvw, O_W, O_NONE, P_c1|P_aso|P_rexr|P_rexx|P_rexb }, /* 2E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 2F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 30 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 31 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 32 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 33 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 34 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 35 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 36 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 37 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 38 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 39 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 3F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 40 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 41 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 42 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 43 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 44 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 45 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 46 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 47 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 48 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 49 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 4F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 50 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 51 */ { UD_Isqrtss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 52 */ { UD_Irsqrtss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 53 */ { UD_Ircpss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 54 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 55 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 56 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 57 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 58 */ { UD_Iaddss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 59 */ { UD_Imulss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 5A */ { UD_Icvtss2sd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 5B */ { UD_Icvttps2dq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 5C */ { UD_Isubss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 5D */ { UD_Iminss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 5E */ { UD_Idivss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 5F */ { UD_Imaxss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 60 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 61 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 62 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 63 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 64 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 65 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 66 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 67 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 68 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 69 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 6F */ { UD_Imovdqu, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 70 */ { UD_Ipshufhw, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 71 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 72 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 73 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 74 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 75 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 76 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 77 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 78 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 79 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 7E */ { UD_Imovq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 7F */ { UD_Imovdqu, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 80 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 81 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 82 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 83 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 84 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 85 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 86 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 87 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 88 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 89 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 8F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 90 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 91 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 92 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 93 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 94 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 95 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 96 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 97 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 98 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 99 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9A */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9B */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9C */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9D */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9E */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 9F */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* A9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* AF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* B9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* BF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C0 */ { UD_Ixadd, O_Eb, O_Gb, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* C1 */ { UD_Ixadd, O_Ev, O_Gv, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* C2 */ { UD_Icmpss, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* C3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C7 */ { UD_Igrp_reg, O_NONE, O_NONE, O_NONE, ITAB__PFX_SSEF3__0F__OP_C7__REG }, /* C8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* C9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* CF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D6 */ { UD_Imovq2dq, O_V, O_PR, O_NONE, P_aso }, /* D7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* D9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* DF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E6 */ { UD_Icvtdq2pd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* E7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* E9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* EA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* EB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* EC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* ED */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* EE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* EF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F0 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F1 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F2 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F3 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F4 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F5 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F6 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F7 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F8 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* F9 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FA */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FB */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FC */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FD */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FE */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* FF */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__pfx_ssef3__0f__op_c7__reg[8] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 02 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 03 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 04 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 05 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 06 */ { UD_Igrp_vendor, O_NONE, O_NONE, O_NONE, ITAB__PFX_SSEF3__0F__OP_C7__REG__OP_06__VENDOR }, /* 07 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, }; static struct ud_itab_entry itab__pfx_ssef3__0f__op_c7__reg__op_06__vendor[3] = { /* 00 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 01 */ { UD_Ivmxon, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 02 */ { UD_Ivmxon, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, }; /* the order of this table matches enum ud_itab_index */ struct ud_itab_entry * ud_itab_list[] = { itab__0f, itab__0f__op_00__reg, itab__0f__op_01__reg, itab__0f__op_01__reg__op_00__mod, itab__0f__op_01__reg__op_00__mod__op_01__rm, itab__0f__op_01__reg__op_00__mod__op_01__rm__op_01__vendor, itab__0f__op_01__reg__op_00__mod__op_01__rm__op_02__vendor, itab__0f__op_01__reg__op_00__mod__op_01__rm__op_03__vendor, itab__0f__op_01__reg__op_00__mod__op_01__rm__op_04__vendor, itab__0f__op_01__reg__op_01__mod, itab__0f__op_01__reg__op_01__mod__op_01__rm, itab__0f__op_01__reg__op_02__mod, itab__0f__op_01__reg__op_02__mod__op_01__rm, itab__0f__op_01__reg__op_03__mod, itab__0f__op_01__reg__op_03__mod__op_01__rm, itab__0f__op_01__reg__op_03__mod__op_01__rm__op_00__vendor, itab__0f__op_01__reg__op_03__mod__op_01__rm__op_01__vendor, itab__0f__op_01__reg__op_03__mod__op_01__rm__op_02__vendor, itab__0f__op_01__reg__op_03__mod__op_01__rm__op_03__vendor, itab__0f__op_01__reg__op_03__mod__op_01__rm__op_04__vendor, itab__0f__op_01__reg__op_03__mod__op_01__rm__op_05__vendor, itab__0f__op_01__reg__op_03__mod__op_01__rm__op_06__vendor, itab__0f__op_01__reg__op_03__mod__op_01__rm__op_07__vendor, itab__0f__op_01__reg__op_04__mod, itab__0f__op_01__reg__op_06__mod, itab__0f__op_01__reg__op_07__mod, itab__0f__op_01__reg__op_07__mod__op_01__rm, itab__0f__op_01__reg__op_07__mod__op_01__rm__op_01__vendor, itab__0f__op_0d__reg, itab__0f__op_18__reg, itab__0f__op_71__reg, itab__0f__op_72__reg, itab__0f__op_73__reg, itab__0f__op_78__mode, itab__0f__op_78__mode__op_00__vendor, itab__0f__op_78__mode__op_01__vendor, itab__0f__op_78__mode__op_02__vendor, itab__0f__op_79__mode, itab__0f__op_79__mode__op_00__vendor, itab__0f__op_79__mode__op_01__vendor, itab__0f__op_79__mode__op_02__vendor, itab__0f__op_a6__mod, itab__0f__op_a6__mod__op_01__rm, itab__0f__op_a6__mod__op_01__rm__op_00__reg, itab__0f__op_a7__mod, itab__0f__op_a7__mod__op_01__rm, itab__0f__op_a7__mod__op_01__rm__op_00__reg, itab__0f__op_ae__reg, itab__0f__op_ae__reg__op_04__mod, itab__0f__op_ae__reg__op_05__mod, itab__0f__op_ae__reg__op_05__mod__op_01__rm, itab__0f__op_ae__reg__op_06__mod, itab__0f__op_ae__reg__op_06__mod__op_01__rm, itab__0f__op_ae__reg__op_07__mod, itab__0f__op_ae__reg__op_07__mod__op_01__rm, itab__0f__op_ba__reg, itab__0f__op_c7__reg, itab__0f__op_c7__reg__op_06__vendor, itab__0f__op_c7__reg__op_07__vendor, itab__0f__op_d9__mod, itab__0f__op_d9__mod__op_01__x87, itab__1byte, itab__1byte__op_60__osize, itab__1byte__op_61__osize, itab__1byte__op_63__mode, itab__1byte__op_6d__osize, itab__1byte__op_6f__osize, itab__1byte__op_80__reg, itab__1byte__op_81__reg, itab__1byte__op_82__reg, itab__1byte__op_83__reg, itab__1byte__op_8f__reg, itab__1byte__op_98__osize, itab__1byte__op_99__osize, itab__1byte__op_9c__mode, itab__1byte__op_9c__mode__op_00__osize, itab__1byte__op_9c__mode__op_01__osize, itab__1byte__op_9c__mode__op_02__osize, itab__1byte__op_9d__mode, itab__1byte__op_9d__mode__op_00__osize, itab__1byte__op_9d__mode__op_01__osize, itab__1byte__op_a5__osize, itab__1byte__op_a7__osize, itab__1byte__op_ab__osize, itab__1byte__op_ad__osize, itab__1byte__op_af__osize, itab__1byte__op_c0__reg, itab__1byte__op_c1__reg, itab__1byte__op_c6__reg, itab__1byte__op_c7__reg, itab__1byte__op_cf__osize, itab__1byte__op_d0__reg, itab__1byte__op_d1__reg, itab__1byte__op_d2__reg, itab__1byte__op_d3__reg, itab__1byte__op_d8__mod, itab__1byte__op_d8__mod__op_00__reg, itab__1byte__op_d8__mod__op_01__x87, itab__1byte__op_d9__mod, itab__1byte__op_d9__mod__op_00__reg, itab__1byte__op_d9__mod__op_01__x87, itab__1byte__op_da__mod, itab__1byte__op_da__mod__op_00__reg, itab__1byte__op_da__mod__op_01__x87, itab__1byte__op_db__mod, itab__1byte__op_db__mod__op_00__reg, itab__1byte__op_db__mod__op_01__x87, itab__1byte__op_dc__mod, itab__1byte__op_dc__mod__op_00__reg, itab__1byte__op_dc__mod__op_01__x87, itab__1byte__op_dd__mod, itab__1byte__op_dd__mod__op_00__reg, itab__1byte__op_dd__mod__op_01__x87, itab__1byte__op_de__mod, itab__1byte__op_de__mod__op_00__reg, itab__1byte__op_de__mod__op_01__x87, itab__1byte__op_df__mod, itab__1byte__op_df__mod__op_00__reg, itab__1byte__op_df__mod__op_01__x87, itab__1byte__op_e3__asize, itab__1byte__op_f6__reg, itab__1byte__op_f7__reg, itab__1byte__op_fe__reg, itab__1byte__op_ff__reg, itab__3dnow, itab__pfx_sse66__0f, itab__pfx_sse66__0f__38, itab__pfx_sse66__0f__38__op_80__mode, itab__pfx_sse66__0f__38__op_80__mode__op_01__vendor, itab__pfx_sse66__0f__38__op_80__mode__op_02__vendor, itab__pfx_sse66__0f__38__op_81__mode, itab__pfx_sse66__0f__38__op_81__mode__op_01__vendor, itab__pfx_sse66__0f__38__op_81__mode__op_02__vendor, itab__pfx_sse66__0f__op_71__reg, itab__pfx_sse66__0f__op_72__reg, itab__pfx_sse66__0f__op_73__reg, itab__pfx_sse66__0f__op_c7__reg, itab__pfx_sse66__0f__op_c7__reg__op_06__vendor, itab__pfx_ssef2__0f, itab__pfx_ssef3__0f, itab__pfx_ssef3__0f__op_c7__reg, itab__pfx_ssef3__0f__op_c7__reg__op_06__vendor, }; ksplice-0.9.9/kmodsrc/x86/libudis86/syn-att.c0000644000000000000000000001345611206570615017340 0ustar rootroot/* udis86 - libudis86/syn-att.c * * Copyright (c) 2002-2009 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "types.h" #include "extern.h" #include "decode.h" #include "itab.h" #include "syn.h" /* ----------------------------------------------------------------------------- * opr_cast() - Prints an operand cast. * ----------------------------------------------------------------------------- */ static void opr_cast(struct ud* u, struct ud_operand* op) { switch(op->size) { case 16 : case 32 : mkasm(u, "*"); break; default: break; } } /* ----------------------------------------------------------------------------- * gen_operand() - Generates assembly output for each operand. * ----------------------------------------------------------------------------- */ static void gen_operand(struct ud* u, struct ud_operand* op) { switch(op->type) { case UD_OP_REG: mkasm(u, "%%%s", ud_reg_tab[op->base - UD_R_AL]); break; case UD_OP_MEM: if (u->br_far) opr_cast(u, op); if (u->pfx_seg) mkasm(u, "%%%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]); if (op->offset == 8) { if (op->lval.sbyte < 0) mkasm(u, "-0x%x", (-op->lval.sbyte) & 0xff); else mkasm(u, "0x%x", op->lval.sbyte); } else if (op->offset == 16) mkasm(u, "0x%x", op->lval.uword); else if (op->offset == 32) mkasm(u, "0x%lx", op->lval.udword); else if (op->offset == 64) mkasm(u, "0x" FMT64 "x", op->lval.uqword); if (op->base) mkasm(u, "(%%%s", ud_reg_tab[op->base - UD_R_AL]); if (op->index) { if (op->base) mkasm(u, ","); else mkasm(u, "("); mkasm(u, "%%%s", ud_reg_tab[op->index - UD_R_AL]); } if (op->scale) mkasm(u, ",%d", op->scale); if (op->base || op->index) mkasm(u, ")"); break; case UD_OP_IMM: switch (op->size) { case 8: mkasm(u, "$0x%x", op->lval.ubyte); break; case 16: mkasm(u, "$0x%x", op->lval.uword); break; case 32: mkasm(u, "$0x%lx", op->lval.udword); break; case 64: mkasm(u, "$0x" FMT64 "x", op->lval.uqword); break; default: break; } break; case UD_OP_JIMM: switch (op->size) { case 8: mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sbyte); break; case 16: mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sword); break; case 32: mkasm(u, "0x" FMT64 "x", u->pc + op->lval.sdword); break; default:break; } break; case UD_OP_PTR: switch (op->size) { case 32: mkasm(u, "$0x%x, $0x%x", op->lval.ptr.seg, op->lval.ptr.off & 0xFFFF); break; case 48: mkasm(u, "$0x%x, $0x%lx", op->lval.ptr.seg, op->lval.ptr.off); break; } break; default: return; } } /* ============================================================================= * translates to AT&T syntax * ============================================================================= */ extern void ud_translate_att(struct ud *u) { int size = 0; /* check if P_OSO prefix is used */ if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) { switch (u->dis_mode) { case 16: mkasm(u, "o32 "); break; case 32: case 64: mkasm(u, "o16 "); break; } } /* check if P_ASO prefix was used */ if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) { switch (u->dis_mode) { case 16: mkasm(u, "a32 "); break; case 32: mkasm(u, "a16 "); break; case 64: mkasm(u, "a32 "); break; } } if (u->pfx_lock) mkasm(u, "lock "); if (u->pfx_rep) mkasm(u, "rep "); if (u->pfx_repne) mkasm(u, "repne "); /* special instructions */ switch (u->mnemonic) { case UD_Iretf: mkasm(u, "lret "); break; case UD_Idb: mkasm(u, ".byte 0x%x", u->operand[0].lval.ubyte); return; case UD_Ijmp: case UD_Icall: if (u->br_far) mkasm(u, "l"); mkasm(u, "%s", ud_lookup_mnemonic(u->mnemonic)); break; case UD_Ibound: case UD_Ienter: if (u->operand[0].type != UD_NONE) gen_operand(u, &u->operand[0]); if (u->operand[1].type != UD_NONE) { mkasm(u, ","); gen_operand(u, &u->operand[1]); } return; default: mkasm(u, "%s", ud_lookup_mnemonic(u->mnemonic)); } if (u->c1) size = u->operand[0].size; else if (u->c2) size = u->operand[1].size; else if (u->c3) size = u->operand[2].size; if (size == 8) mkasm(u, "b"); else if (size == 16) mkasm(u, "w"); else if (size == 64) mkasm(u, "q"); mkasm(u, " "); if (u->operand[2].type != UD_NONE) { gen_operand(u, &u->operand[2]); mkasm(u, ", "); } if (u->operand[1].type != UD_NONE) { gen_operand(u, &u->operand[1]); mkasm(u, ", "); } if (u->operand[0].type != UD_NONE) gen_operand(u, &u->operand[0]); } ksplice-0.9.9/kmodsrc/x86/libudis86/x86optable.xml0000644000000000000000000032343511216530430020304 0ustar rootroot ; 0f 0f ; P Q ; 37 ; ; d5 ; Ib ; d4 ; Ib ; 3f ; aso rexr rexx rexb ; 10 ; Eb Gb aso oso rexw rexr rexx rexb ; 11 ; Ev Gv aso rexr rexx rexb ; 12 ; Gb Eb aso oso rexw rexr rexx rexb ; 13 ; Gv Ev ; 14 ; AL Ib oso rexw ; 15 ; rAX Iz aso rexr rexx rexb ; 80 /2 ; Eb Ib aso rexr rexx rexb ; 82 /2 ; Eb Ib aso oso rexw rexr rexx rexb ; 81 /2 ; Ev Iz aso oso rexw rexr rexx rexb ; 83 /2 ; Ev Ib aso rexr rexx rexb ; 00 ; Eb Gb aso oso rexw rexr rexx rexb ; 01 ; Ev Gv aso rexr rexx rexb ; 02 ; Gb Eb aso oso rexw rexr rexx rexb ; 03 ; Gv Ev ; 04 ; AL Ib oso rexw ; 05 ; rAX Iz aso rexr rexx rexb ; 80 /0 ; Eb Ib aso rexr rexx rexb ; 82 /0 ; Eb Ib aso oso rexw rexr rexx rexb ; 81 /0 ; Ev Iz aso oso rexw rexr rexx rexb ; 83 /0 ; Ev Ib aso rexr rexx rexb ; sse66 0f 58 ; V W aso rexr rexx rexb ; 0f 58 ; V W aso rexr rexx rexb ; ssef2 0f 58 ; V W aso rexr rexx rexb ; ssef3 0f 58 ; V W aso rexr rexx rexb ; sse66 0f d0 ; V W aso rexr rexx rexb ; ssef2 0f d0 ; V W aso rexr rexx rexb ; 20 ; Eb Gb aso oso rexw rexr rexx rexb ; 21 ; Ev Gv aso rexr rexx rexb ; 22 ; Gb Eb aso oso rexw rexr rexx rexb ; 23 ; Gv Ev ; 24 ; AL Ib oso rexw ; 25 ; rAX Iz aso rexw rexr rexx rexb ; 80 /4 ; Eb Ib aso rexr rexx rexb ; 82 /4 ; Eb Ib aso oso rexw rexr rexx rexb ; 81 /4 ; Ev Iz aso oso rexw rexr rexx rexb ; 83 /4 ; Ev Ib aso rexr rexx rexb ; sse66 0f 54 ; V W aso rexr rexx rexb ; 0f 54 ; V W aso rexr rexx rexb ; sse66 0f 55 ; V W aso rexr rexx rexb ; 0f 55 ; V W aso ; 63 /M16 ; Ew Gw aso ; 63 /M32 ; Ew Gw aso oso rexw rexx rexr rexb ; 63 /M64 ; Gv Ed aso oso ; 62 ; Gv M aso oso rexw rexr rexx rexb ; 0f bc ; Gv Ev aso oso rexw rexr rexx rexb ; 0f bd ; Gv Ev oso rexw rexb ; 0f c8 ; rAXr8 oso rexw rexb ; 0f c9 ; rCXr9 oso rexw rexb ; 0f ca ; rDXr10 oso rexw rexb ; 0f cb ; rBXr11 oso rexw rexb ; 0f cc ; rSPr12 oso rexw rexb ; 0f cd ; rBPr13 oso rexw rexb ; 0f ce ; rSIr14 oso rexw rexb ; 0f cf ; rDIr15 aso oso rexw rexr rexx rexb ; 0F BA /4 ; Ev Ib aso oso rexw rexr rexx rexb ; 0f a3 ; Ev Gv aso oso rexw rexr rexx rexb ; 0f bb ; Ev Gv aso oso rexw rexr rexx rexb ; 0F BA /7 ; Ev Ib aso oso rexw rexr rexx rexb ; 0f b3 ; Ev Gv aso oso rexw rexr rexx rexb ; 0F BA /6 ; Ev Ib aso oso rexw rexr rexx rexb ; 0f ab ; Ev Gv aso oso rexw rexr rexx rexb ; 0F BA /5 ; Ev Ib aso oso rexw rexr rexx rexb ; FF /2 ; Ev aso oso rexw rexr rexx rexb ; FF /3 ; Ep oso ; e8 ; Jz oso ; 9a ; Ap oso rexw ; 98 /O16 ; oso rexw ; 98 /O32 ; oso rexw ; 98 /O64 ; f8 ; fc ; aso rexw rexr rexx rexb ; 0F AE /7 /mod=!11 ; M 0F 01 /3 /mod=11 /rm=5 ; AMD fa ; 0f 06 ; f5 ; aso oso rexw rexr rexx rexb ; 0f 40 ; Gv Ev aso oso rexw rexr rexx rexb ; 0f 41 ; Gv Ev aso oso rexw rexr rexx rexb ; 0f 42 ; Gv Ev aso oso rexw rexr rexx rexb ; 0f 43 ; Gv Ev aso oso rexw rexr rexx rexb ; 0f 44 ; Gv Ev aso oso rexw rexr rexx rexb ; 0f 45 ; Gv Ev aso oso rexw rexr rexx rexb ; 0f 46 ; Gv Ev aso oso rexw rexr rexx rexb ; 0f 47 ; Gv Ev aso oso rexw rexr rexx rexb ; 0f 48 ; Gv Ev aso oso rexw rexr rexx rexb ; 0f 49 ; Gv Ev aso oso rexw rexr rexx rexb ; 0f 4a ; Gv Ev aso oso rexw rexr rexx rexb ; 0f 4b ; Gv Ev aso oso rexw rexr rexx rexb ; 0f 4c ; Gv Ev aso oso rexw rexr rexx rexb ; 0f 4d ; Gv Ev aso oso rexw rexr rexx rexb ; 0f 4e ; Gv Ev aso oso rexw rexr rexx rexb ; 0f 4f ; Gv Ev aso rexr rexx rexb ; 38 ; Eb Gb aso oso rexw rexr rexx rexb ; 39 ; Ev Gv aso rexr rexx rexb ; 3a ; Gb Eb aso oso rexw rexr rexx rexb ; 3b ; Gv Ev ; 3c ; AL Ib oso rexw ; 3d ; rAX Iz aso rexr rexx rexb ; 80 /7 ; Eb Ib aso rexr rexx rexb ; 82 /7 ; Eb Ib aso oso rexw rexr rexx rexb ; 81 /7 ; Ev Iz aso oso rexw rexr rexx rexb ; 83 /7 ; Ev Ib aso rexr rexx rexb ; sse66 0f c2 ; V W Ib aso rexr rexx rexb ; 0f c2 ; V W Ib a6 ; oso rexw ; a7 /O16 ; oso rexw ; a7 /O32 ; aso rexr rexx rexb ; ssef2 0f c2 ; V W Ib oso rexw ; a7 /O64 ; aso rexr rexx rexb ; ssef3 0f c2 ; V W Ib aso rexr rexx rexb ; 0f b0 ; Eb Gb aso oso rexw rexr rexx rexb ; 0f b1 ; Ev Gv aso rexr rexx rexb ; 0F C7 /1 ; M aso rexr rexx rexb ; sse66 0f 2f ; V W aso rexr rexx rexb ; 0f 2f ; V W 0f a2 ; aso rexr rexx rexb ; ssef3 0f e6 ; V W aso rexr rexx rexb ; 0f 5b ; V W aso rexr rexx rexb ; ssef2 0f e6 ; V W aso rexr rexx rexb ; sse66 0f 2d ; P W aso rexr rexx rexb ; sse66 0f 5a ; V W aso rexr rexx rexb ; 0f 2a ; V Q aso rexr rexx rexb ; sse66 0f 2a ; V Q aso rexr rexx rexb ; sse66 0f 5b ; V W aso rexr rexx rexb ; 0f 2d ; P W aso rexr rexx rexb ; 0f 5a ; V W aso rexr rexx rexb ; ssef2 0f 2d ; Gvw W aso rexr rexx rexb ; ssef2 0f 5a ; V W aso rexr rexx rexb ; ssef3 0f 2a ; V Ex aso rexr rexx rexb ; ssef3 0f 2d ; Gvw W aso rexr rexx rexb ; ssef3 0f 5a ; V W aso rexr rexx rexb ; sse66 0f 2c ; P W ; sse66 0f e6 ; V W aso rexr rexx rexb ; ssef3 0f 5b ; V W aso rexr rexx rexb ; 0f 2c ; P W aso rexr rexx rexb ; ssef2 0f 2c ; Gvw W aso rexw rexr rexx rexb ; ssef2 0f 2a ; V Ex aso rexr rexx rexb ; ssef3 0f 2c ; Gvw W oso rexw ; 99 /O16 ; oso rexw ; 99 /O32 ; oso rexw ; 99 /O64 ; ; 27 ; ; 2f ; oso ; 48 ; eAX oso ; 49 ; eCX oso ; 4a ; eDX oso ; 4b ; eBX oso ; 4c ; eSP oso ; 4d ; eBP oso ; 4e ; eSI oso ; 4f ; eDI aso rexw rexr rexx rexb ; FE /1 ; Eb aso oso rexw rexr rexx rexb ; FF /1 ; Ev aso oso rexw rexr rexx rexb ; F7 /6 ; Ev aso rexw rexr rexx rexb ; F6 /6 ; Eb aso rexr rexx rexb ; sse66 0f 5e ; V W aso rexr rexx rexb ; 0f 5e ; V W aso rexr rexx rexb ; ssef2 0f 5e ; V W aso rexr rexx rexb ; ssef3 0f 5e ; V W 0f 77 ; ; c8 ; Iw Ib 0F D9 /mod=11 /x87=30 ; X87 0F D9 /mod=11 /x87=21 ; X87 X87 aso rexr rexx rexb ; DC /mod=!11 /0 ; Mq aso rexr rexx rexb ; D8 /mod=!11 /0 ; Md DC /mod=11 /x87=00 ; ST0 ST0 DC /mod=11 /x87=01 ; ST1 ST0 DC /mod=11 /x87=02 ; ST2 ST0 DC /mod=11 /x87=03 ; ST3 ST0 DC /mod=11 /x87=04 ; ST4 ST0 DC /mod=11 /x87=05 ; ST5 ST0 DC /mod=11 /x87=06 ; ST6 ST0 DC /mod=11 /x87=07 ; ST7 ST0 D8 /mod=11 /x87=00 ; ST0 ST0 D8 /mod=11 /x87=01 ; ST0 ST1 D8 /mod=11 /x87=02 ; ST0 ST2 D8 /mod=11 /x87=03 ; ST0 ST3 D8 /mod=11 /x87=04 ; ST0 ST4 D8 /mod=11 /x87=05 ; ST0 ST5 D8 /mod=11 /x87=06 ; ST0 ST6 D8 /mod=11 /x87=07 ; ST0 ST7 X87 DE /mod=11 /x87=00 ; ST0 ST0 DE /mod=11 /x87=01 ; ST1 ST0 DE /mod=11 /x87=02 ; ST2 ST0 DE /mod=11 /x87=03 ; ST3 ST0 DE /mod=11 /x87=04 ; ST4 ST0 DE /mod=11 /x87=05 ; ST5 ST0 DE /mod=11 /x87=06 ; ST6 ST0 DE /mod=11 /x87=07 ; ST7 ST0 X87 X87 aso rexr rexx rexb ; DF /mod=!11 /4 ; Mt X87 aso rexr rexx rexb ; DF /mod=!11 /6 ; Mt X87 D9 /mod=11 /x87=20 ; DB /mod=11 /x87=22 ; X87 DA /mod=11 /x87=00 ; ST0 ST0 DA /mod=11 /x87=01 ; ST0 ST1 DA /mod=11 /x87=02 ; ST0 ST2 DA /mod=11 /x87=03 ; ST0 ST3 DA /mod=11 /x87=04 ; ST0 ST4 DA /mod=11 /x87=05 ; ST0 ST5 DA /mod=11 /x87=06 ; ST0 ST6 DA /mod=11 /x87=07 ; ST0 ST7 X87 DA /mod=11 /x87=08 ; ST0 ST0 DA /mod=11 /x87=09 ; ST0 ST1 DA /mod=11 /x87=0A ; ST0 ST2 DA /mod=11 /x87=0B ; ST0 ST3 DA /mod=11 /x87=0C ; ST0 ST4 DA /mod=11 /x87=0D ; ST0 ST5 DA /mod=11 /x87=0E ; ST0 ST6 DA /mod=11 /x87=0F ; ST0 ST7 X87 DA /mod=11 /x87=10 ; ST0 ST0 DA /mod=11 /x87=11 ; ST0 ST1 DA /mod=11 /x87=12 ; ST0 ST2 DA /mod=11 /x87=13 ; ST0 ST3 DA /mod=11 /x87=14 ; ST0 ST4 DA /mod=11 /x87=15 ; ST0 ST5 DA /mod=11 /x87=16 ; ST0 ST6 DA /mod=11 /x87=17 ; ST0 ST7 X87 DA /mod=11 /x87=18 ; ST0 ST0 DA /mod=11 /x87=19 ; ST0 ST1 DA /mod=11 /x87=1A ; ST0 ST2 DA /mod=11 /x87=1B ; ST0 ST3 DA /mod=11 /x87=1C ; ST0 ST4 DA /mod=11 /x87=1D ; ST0 ST5 DA /mod=11 /x87=1E ; ST0 ST6 DA /mod=11 /x87=1F ; ST0 ST7 X87 DB /mod=11 /x87=00 ; ST0 ST0 DB /mod=11 /x87=01 ; ST0 ST1 DB /mod=11 /x87=02 ; ST0 ST2 DB /mod=11 /x87=03 ; ST0 ST3 DB /mod=11 /x87=04 ; ST0 ST4 DB /mod=11 /x87=05 ; ST0 ST5 DB /mod=11 /x87=06 ; ST0 ST6 DB /mod=11 /x87=07 ; ST0 ST7 X87 DB /mod=11 /x87=08 ; ST0 ST0 DB /mod=11 /x87=09 ; ST0 ST1 DB /mod=11 /x87=0A ; ST0 ST2 DB /mod=11 /x87=0B ; ST0 ST3 DB /mod=11 /x87=0C ; ST0 ST4 DB /mod=11 /x87=0D ; ST0 ST5 DB /mod=11 /x87=0E ; ST0 ST6 DB /mod=11 /x87=0F ; ST0 ST7 X87 DB /mod=11 /x87=10 ; ST0 ST0 DB /mod=11 /x87=11 ; ST0 ST1 DB /mod=11 /x87=12 ; ST0 ST2 DB /mod=11 /x87=13 ; ST0 ST3 DB /mod=11 /x87=14 ; ST0 ST4 DB /mod=11 /x87=15 ; ST0 ST5 DB /mod=11 /x87=16 ; ST0 ST6 DB /mod=11 /x87=17 ; ST0 ST7 X87 DB /mod=11 /x87=18 ; ST0 ST0 DB /mod=11 /x87=19 ; ST0 ST1 DB /mod=11 /x87=1A ; ST0 ST2 DB /mod=11 /x87=1B ; ST0 ST3 DB /mod=11 /x87=1C ; ST0 ST4 DB /mod=11 /x87=1D ; ST0 ST5 DB /mod=11 /x87=1E ; ST0 ST6 DB /mod=11 /x87=1F ; ST0 ST7 X87 DB /mod=11 /x87=28 ; ST0 ST0 DB /mod=11 /x87=29 ; ST0 ST1 DB /mod=11 /x87=2A ; ST0 ST2 DB /mod=11 /x87=2B ; ST0 ST3 DB /mod=11 /x87=2C ; ST0 ST4 DB /mod=11 /x87=2D ; ST0 ST5 DB /mod=11 /x87=2E ; ST0 ST6 DB /mod=11 /x87=2F ; ST0 ST7 X87 aso rexr rexx rexb ; D8 /mod=!11 /2 ; Md aso rexr rexx rexb ; DC /mod=!11 /2 ; Mq D8 /mod=11 /x87=10 ; ST0 ST0 D8 /mod=11 /x87=11 ; ST0 ST1 D8 /mod=11 /x87=12 ; ST0 ST2 D8 /mod=11 /x87=13 ; ST0 ST3 D8 /mod=11 /x87=14 ; ST0 ST4 D8 /mod=11 /x87=15 ; ST0 ST5 D8 /mod=11 /x87=16 ; ST0 ST6 D8 /mod=11 /x87=17 ; ST0 ST7 X87 DC /mod=11 /x87=10 ; ST0 DC /mod=11 /x87=11 ; ST1 DC /mod=11 /x87=12 ; ST2 DC /mod=11 /x87=13 ; ST3 DC /mod=11 /x87=14 ; ST4 DC /mod=11 /x87=15 ; ST5 DC /mod=11 /x87=16 ; ST6 DC /mod=11 /x87=17 ; ST7 X87 UNDOC DC /mod=11 /x87=18 ; ST0 DC /mod=11 /x87=19 ; ST1 DC /mod=11 /x87=1A ; ST2 DC /mod=11 /x87=1B ; ST3 DC /mod=11 /x87=1C ; ST4 DC /mod=11 /x87=1D ; ST5 DC /mod=11 /x87=1E ; ST6 DC /mod=11 /x87=1F ; ST7 X87 UNDOC DB /mod=11 /x87=30 ; ST0 ST0 DB /mod=11 /x87=31 ; ST0 ST1 DB /mod=11 /x87=32 ; ST0 ST2 DB /mod=11 /x87=33 ; ST0 ST3 DB /mod=11 /x87=34 ; ST0 ST4 DB /mod=11 /x87=35 ; ST0 ST5 DB /mod=11 /x87=36 ; ST0 ST6 DB /mod=11 /x87=37 ; ST0 ST7 X87 DF /mod=11 /x87=28 ; ST0 ST0 DF /mod=11 /x87=29 ; ST0 ST1 DF /mod=11 /x87=2A ; ST0 ST2 DF /mod=11 /x87=2B ; ST0 ST3 DF /mod=11 /x87=2C ; ST0 ST4 DF /mod=11 /x87=2D ; ST0 ST5 DF /mod=11 /x87=2E ; ST0 ST6 DF /mod=11 /x87=2F ; ST0 ST7 X87 DF /mod=11 /x87=30 ; ST0 ST0 DF /mod=11 /x87=31 ; ST0 ST1 DF /mod=11 /x87=32 ; ST0 ST2 DF /mod=11 /x87=33 ; ST0 ST3 DF /mod=11 /x87=34 ; ST0 ST4 DF /mod=11 /x87=35 ; ST0 ST5 DF /mod=11 /x87=36 ; ST0 ST6 DF /mod=11 /x87=37 ; ST0 ST7 X87 aso rexr rexx rexb ; D8 /mod=!11 /3 ; Md aso rexr rexx rexb ; DC /mod=!11 /3 ; Mq D8 /mod=11 /x87=18 ; ST0 ST0 D8 /mod=11 /x87=19 ; ST0 ST1 D8 /mod=11 /x87=1A ; ST0 ST2 D8 /mod=11 /x87=1B ; ST0 ST3 D8 /mod=11 /x87=1C ; ST0 ST4 D8 /mod=11 /x87=1D ; ST0 ST5 D8 /mod=11 /x87=1E ; ST0 ST6 D8 /mod=11 /x87=1F ; ST0 ST7 X87 DE /mod=11 /x87=10 ; ST0 DE /mod=11 /x87=11 ; ST1 DE /mod=11 /x87=12 ; ST2 DE /mod=11 /x87=13 ; ST3 DE /mod=11 /x87=14 ; ST4 DE /mod=11 /x87=15 ; ST5 DE /mod=11 /x87=16 ; ST6 DE /mod=11 /x87=17 ; ST7 X87 UNDOC DE /mod=11 /x87=19 ; X87 D9 /mod=11 /x87=3F ; X87 D9 /mod=11 /x87=36 ; X87 aso rexr rexx rexb ; DC /mod=!11 /6 ; Mq DC /mod=11 /x87=38 ; ST0 ST0 DC /mod=11 /x87=39 ; ST1 ST0 DC /mod=11 /x87=3A ; ST2 ST0 DC /mod=11 /x87=3B ; ST3 ST0 DC /mod=11 /x87=3C ; ST4 ST0 DC /mod=11 /x87=3D ; ST5 ST0 DC /mod=11 /x87=3E ; ST6 ST0 DC /mod=11 /x87=3F ; ST7 ST0 aso rexr rexx rexb ; D8 /mod=!11 /6 ; Md D8 /mod=11 /x87=30 ; ST0 ST0 D8 /mod=11 /x87=31 ; ST0 ST1 D8 /mod=11 /x87=32 ; ST0 ST2 D8 /mod=11 /x87=33 ; ST0 ST3 D8 /mod=11 /x87=34 ; ST0 ST4 D8 /mod=11 /x87=35 ; ST0 ST5 D8 /mod=11 /x87=36 ; ST0 ST6 D8 /mod=11 /x87=37 ; ST0 ST7 X87 DE /mod=11 /x87=38 ; ST0 ST0 DE /mod=11 /x87=39 ; ST1 ST0 DE /mod=11 /x87=3A ; ST2 ST0 DE /mod=11 /x87=3B ; ST3 ST0 DE /mod=11 /x87=3C ; ST4 ST0 DE /mod=11 /x87=3D ; ST5 ST0 DE /mod=11 /x87=3E ; ST6 ST0 DE /mod=11 /x87=3F ; ST7 ST0 X87 aso rexr rexx rexb ; DC /mod=!11 /7 ; Mq DC /mod=11 /x87=30 ; ST0 ST0 DC /mod=11 /x87=31 ; ST1 ST0 DC /mod=11 /x87=32 ; ST2 ST0 DC /mod=11 /x87=33 ; ST3 ST0 DC /mod=11 /x87=34 ; ST4 ST0 DC /mod=11 /x87=35 ; ST5 ST0 DC /mod=11 /x87=36 ; ST6 ST0 DC /mod=11 /x87=37 ; ST7 ST0 aso rexr rexx rexb ; D8 /mod=!11 /7 ; Md D8 /mod=11 /x87=38 ; ST0 ST0 D8 /mod=11 /x87=39 ; ST0 ST1 D8 /mod=11 /x87=3A ; ST0 ST2 D8 /mod=11 /x87=3B ; ST0 ST3 D8 /mod=11 /x87=3C ; ST0 ST4 D8 /mod=11 /x87=3D ; ST0 ST5 D8 /mod=11 /x87=3E ; ST0 ST6 D8 /mod=11 /x87=3F ; ST0 ST7 X87 DE /mod=11 /x87=30 ; ST0 ST0 DE /mod=11 /x87=31 ; ST1 ST0 DE /mod=11 /x87=32 ; ST2 ST0 DE /mod=11 /x87=33 ; ST3 ST0 DE /mod=11 /x87=34 ; ST4 ST0 DE /mod=11 /x87=35 ; ST5 ST0 DE /mod=11 /x87=36 ; ST6 ST0 DE /mod=11 /x87=37 ; ST7 ST0 X87 0f 0e ; DD /mod=11 /x87=00 ; ST0 DD /mod=11 /x87=01 ; ST1 DD /mod=11 /x87=02 ; ST2 DD /mod=11 /x87=03 ; ST3 DD /mod=11 /x87=04 ; ST4 DD /mod=11 /x87=05 ; ST5 DD /mod=11 /x87=06 ; ST6 DD /mod=11 /x87=07 ; ST7 X87 DF /mod=11 /x87=00 ; ST0 DF /mod=11 /x87=01 ; ST1 DF /mod=11 /x87=02 ; ST2 DF /mod=11 /x87=03 ; ST3 DF /mod=11 /x87=04 ; ST4 DF /mod=11 /x87=05 ; ST5 DF /mod=11 /x87=06 ; ST6 DF /mod=11 /x87=07 ; ST7 X87 aso rexr rexx rexb ; DE /mod=!11 /2 ; Mw aso rexr rexx rexb ; DA /mod=!11 /2 ; Md X87 aso rexr rexx rexb ; DE /mod=!11 /3 ; Mw aso rexr rexx rexb ; DA /mod=!11 /3 ; Md X87 aso rexr rexx rexb ; DF /mod=!11 /0 ; Mw aso rexr rexx rexb ; DF /mod=!11 /5 ; Mq aso rexr rexx rexb ; DB /mod=!11 /0 ; Md X87 D9 /mod=11 /x87=37 ; X87 DB /mod=11 /x87=23 ; X87 aso rexr rexx rexb ; DA /mod=!11 /0 ; Md aso rexr rexx rexb ; DE /mod=!11 /0 ; Mw X87 aso rexr rexx rexb ; DA /mod=!11 /7 ; Md aso rexr rexx rexb ; DE /mod=!11 /7 ; Mw X87 aso rexr rexx rexb ; DA /mod=!11 /6 ; Md aso rexr rexx rexb ; DE /mod=!11 /6 ; Mw X87 aso rexr rexx rexb ; DA /mod=!11 /4 ; Md aso rexr rexx rexb ; DE /mod=!11 /4 ; Mw X87 aso rexr rexx rexb ; DA /mod=!11 /5 ; Md aso rexr rexx rexb ; DE /mod=!11 /5 ; Mw X87 aso rexr rexx rexb ; DF /mod=!11 /2 ; Mw aso rexr rexx rexb ; DB /mod=!11 /2 ; Md X87 aso rexr rexx rexb ; DF /mod=!11 /3 ; Mw aso rexr rexx rexb ; DF /mod=!11 /7 ; Mq aso rexr rexx rexb ; DB /mod=!11 /3 ; Md X87 aso rexr rexx rexb ; DB /mod=!11 /1 ; Md aso rexr rexx rexb ; DD /mod=!11 /1 ; Mq aso rexr rexx rexb ; DF /mod=!11 /1 ; Mw X87 aso rexr rexx rexb ; DB /mod=!11 /5 ; Mt aso rexr rexx rexb ; DD /mod=!11 /0 ; Mq aso rexr rexx rexb ; D9 /mod=!11 /0 ; Md D9 /mod=11 /x87=00 ; ST0 ST0 D9 /mod=11 /x87=01 ; ST0 ST1 D9 /mod=11 /x87=02 ; ST0 ST2 D9 /mod=11 /x87=03 ; ST0 ST3 D9 /mod=11 /x87=04 ; ST0 ST4 D9 /mod=11 /x87=05 ; ST0 ST5 D9 /mod=11 /x87=06 ; ST0 ST6 D9 /mod=11 /x87=07 ; ST0 ST7 X87 D9 /mod=11 /x87=28 ; X87 D9 /mod=11 /x87=29 ; X87 D9 /mod=11 /x87=2A ; X87 D9 /mod=11 /x87=2B ; X87 D9 /mod=11 /x87=2C ; X87 D9 /mod=11 /x87=2D ; X87 D9 /mod=11 /x87=2E ; X87 aso rexr rexx rexb ; D9 /mod=!11 /5 ; Mw X87 aso rexr rexx rexb ; D9 /mod=!11 /4 ; M X87 aso rexr rexx rexb ; DC /mod=!11 /1 ; Mq DC /mod=11 /x87=08 ; ST0 ST0 DC /mod=11 /x87=09 ; ST1 ST0 DC /mod=11 /x87=0A ; ST2 ST0 DC /mod=11 /x87=0B ; ST3 ST0 DC /mod=11 /x87=0C ; ST4 ST0 DC /mod=11 /x87=0D ; ST5 ST0 DC /mod=11 /x87=0E ; ST6 ST0 DC /mod=11 /x87=0F ; ST7 ST0 aso rexr rexx rexb ; D8 /mod=!11 /1 ; Md D8 /mod=11 /x87=08 ; ST0 ST0 D8 /mod=11 /x87=09 ; ST0 ST1 D8 /mod=11 /x87=0A ; ST0 ST2 D8 /mod=11 /x87=0B ; ST0 ST3 D8 /mod=11 /x87=0C ; ST0 ST4 D8 /mod=11 /x87=0D ; ST0 ST5 D8 /mod=11 /x87=0E ; ST0 ST6 D8 /mod=11 /x87=0F ; ST0 ST7 X87 DE /mod=11 /x87=08 ; ST0 ST0 DE /mod=11 /x87=09 ; ST1 ST0 DE /mod=11 /x87=0A ; ST2 ST0 DE /mod=11 /x87=0B ; ST3 ST0 DE /mod=11 /x87=0C ; ST4 ST0 DE /mod=11 /x87=0D ; ST5 ST0 DE /mod=11 /x87=0E ; ST6 ST0 DE /mod=11 /x87=0F ; ST7 ST0 X87 aso rexr rexx rexb ; DA /mod=!11 /1 ; Md aso rexr rexx rexb ; DE /mod=!11 /1 ; Mw X87 D9 /mod=11 /x87=10 ; X87 D9 /mod=11 /x87=33 ; X87 D9 /mod=11 /x87=38 ; X87 D9 /mod=11 /x87=35 ; X87 D9 /mod=11 /x87=32 ; X87 D9 /mod=11 /x87=3C ; X87 aso rexr rexx rexb ; DD /mod=!11 /4 ; M X87 aso rexr rexx rexb ; DD /mod=!11 /6 ; M X87 D9 /mod=11 /x87=3D ; X87 D9 /mod=11 /x87=3E ; X87 D9 /mod=11 /x87=3B ; X87 D9 /mod=11 /x87=3A ; X87 aso rexr rexx rexb ; DB /mod=!11 /7 ; Mt aso rexr rexx rexb ; DD /mod=!11 /3 ; Mq aso rexr rexx rexb ; D9 /mod=!11 /3 ; Md DD /mod=11 /x87=18 ; ST0 DD /mod=11 /x87=19 ; ST1 DD /mod=11 /x87=1A ; ST2 DD /mod=11 /x87=1B ; ST3 DD /mod=11 /x87=1C ; ST4 DD /mod=11 /x87=1D ; ST5 DD /mod=11 /x87=1E ; ST6 DD /mod=11 /x87=1F ; ST7 X87 D9 /mod=11 /x87=18 ; ST0 D9 /mod=11 /x87=19 ; ST1 D9 /mod=11 /x87=1A ; ST2 D9 /mod=11 /x87=1B ; ST3 D9 /mod=11 /x87=1C ; ST4 D9 /mod=11 /x87=1D ; ST5 D9 /mod=11 /x87=1E ; ST6 D9 /mod=11 /x87=1F ; ST7 DF /mod=11 /x87=10 ; ST0 DF /mod=11 /x87=11 ; ST1 DF /mod=11 /x87=12 ; ST2 DF /mod=11 /x87=13 ; ST3 DF /mod=11 /x87=14 ; ST4 DF /mod=11 /x87=15 ; ST5 DF /mod=11 /x87=16 ; ST6 DF /mod=11 /x87=17 ; ST7 DF /mod=11 /x87=18 ; ST0 DF /mod=11 /x87=19 ; ST1 DF /mod=11 /x87=1A ; ST2 DF /mod=11 /x87=1B ; ST3 DF /mod=11 /x87=1C ; ST4 DF /mod=11 /x87=1D ; ST5 DF /mod=11 /x87=1E ; ST6 DF /mod=11 /x87=1F ; ST7 aso rexr rexx rexb ; D9 /mod=!11 /2 ; Md aso rexr rexx rexb ; DD /mod=!11 /2 ; Mq DD /mod=11 /x87=10 ; ST0 DD /mod=11 /x87=11 ; ST1 DD /mod=11 /x87=12 ; ST2 DD /mod=11 /x87=13 ; ST3 DD /mod=11 /x87=14 ; ST4 DD /mod=11 /x87=15 ; ST5 DD /mod=11 /x87=16 ; ST6 DD /mod=11 /x87=17 ; ST7 X87 aso rexr rexx rexb ; D9 /mod=!11 /7 ; Mw X87 aso rexr rexx rexb ; D9 /mod=!11 /6 ; M X87 aso rexr rexx rexb ; DD /mod=!11 /7 ; Mw DF /mod=11 /x87=20 ; AX X87 aso rexr rexx rexb ; D8 /mod=!11 /4 ; Md aso rexr rexx rexb ; DC /mod=!11 /4 ; Mq D8 /mod=11 /x87=20 ; ST0 ST0 D8 /mod=11 /x87=21 ; ST0 ST1 D8 /mod=11 /x87=22 ; ST0 ST2 D8 /mod=11 /x87=23 ; ST0 ST3 D8 /mod=11 /x87=24 ; ST0 ST4 D8 /mod=11 /x87=25 ; ST0 ST5 D8 /mod=11 /x87=26 ; ST0 ST6 D8 /mod=11 /x87=27 ; ST0 ST7 DC /mod=11 /x87=28 ; ST0 ST0 DC /mod=11 /x87=29 ; ST1 ST0 DC /mod=11 /x87=2A ; ST2 ST0 DC /mod=11 /x87=2B ; ST3 ST0 DC /mod=11 /x87=2C ; ST4 ST0 DC /mod=11 /x87=2D ; ST5 ST0 DC /mod=11 /x87=2E ; ST6 ST0 DC /mod=11 /x87=2F ; ST7 ST0 X87 DE /mod=11 /x87=28 ; ST0 ST0 DE /mod=11 /x87=29 ; ST1 ST0 DE /mod=11 /x87=2A ; ST2 ST0 DE /mod=11 /x87=2B ; ST3 ST0 DE /mod=11 /x87=2C ; ST4 ST0 DE /mod=11 /x87=2D ; ST5 ST0 DE /mod=11 /x87=2E ; ST6 ST0 DE /mod=11 /x87=2F ; ST7 ST0 X87 aso rexr rexx rexb ; DC /mod=!11 /5 ; Mq D8 /mod=11 /x87=28 ; ST0 ST0 D8 /mod=11 /x87=29 ; ST0 ST1 D8 /mod=11 /x87=2A ; ST0 ST2 D8 /mod=11 /x87=2B ; ST0 ST3 D8 /mod=11 /x87=2C ; ST0 ST4 D8 /mod=11 /x87=2D ; ST0 ST5 D8 /mod=11 /x87=2E ; ST0 ST6 D8 /mod=11 /x87=2F ; ST0 ST7 DC /mod=11 /x87=20 ; ST0 ST0 DC /mod=11 /x87=21 ; ST1 ST0 DC /mod=11 /x87=22 ; ST2 ST0 DC /mod=11 /x87=23 ; ST3 ST0 DC /mod=11 /x87=24 ; ST4 ST0 DC /mod=11 /x87=25 ; ST5 ST0 DC /mod=11 /x87=26 ; ST6 ST0 DC /mod=11 /x87=27 ; ST7 ST0 aso rexr rexx rexb ; D8 /mod=!11 /5 ; Md X87 DE /mod=11 /x87=20 ; ST0 ST0 DE /mod=11 /x87=21 ; ST1 ST0 DE /mod=11 /x87=22 ; ST2 ST0 DE /mod=11 /x87=23 ; ST3 ST0 DE /mod=11 /x87=24 ; ST4 ST0 DE /mod=11 /x87=25 ; ST5 ST0 DE /mod=11 /x87=26 ; ST6 ST0 DE /mod=11 /x87=27 ; ST7 ST0 X87 D9 /mod=11 /x87=24 ; X87 DD /mod=11 /x87=20 ; ST0 DD /mod=11 /x87=21 ; ST1 DD /mod=11 /x87=22 ; ST2 DD /mod=11 /x87=23 ; ST3 DD /mod=11 /x87=24 ; ST4 DD /mod=11 /x87=25 ; ST5 DD /mod=11 /x87=26 ; ST6 DD /mod=11 /x87=27 ; ST7 X87 DD /mod=11 /x87=28 ; ST0 DD /mod=11 /x87=29 ; ST1 DD /mod=11 /x87=2A ; ST2 DD /mod=11 /x87=2B ; ST3 DD /mod=11 /x87=2C ; ST4 DD /mod=11 /x87=2D ; ST5 DD /mod=11 /x87=2E ; ST6 DD /mod=11 /x87=2F ; ST7 X87 DA /mod=11 /x87=29 ; X87 D9 /mod=11 /x87=25 ; X87 D9 /mod=11 /x87=08 ; ST0 ST0 D9 /mod=11 /x87=09 ; ST0 ST1 D9 /mod=11 /x87=0A ; ST0 ST2 D9 /mod=11 /x87=0B ; ST0 ST3 D9 /mod=11 /x87=0C ; ST0 ST4 D9 /mod=11 /x87=0D ; ST0 ST5 D9 /mod=11 /x87=0E ; ST0 ST6 D9 /mod=11 /x87=0F ; ST0 ST7 X87 DD /mod=11 /x87=08 ; ST0 DD /mod=11 /x87=09 ; ST1 DD /mod=11 /x87=0A ; ST2 DD /mod=11 /x87=0B ; ST3 DD /mod=11 /x87=0C ; ST4 DD /mod=11 /x87=0D ; ST5 DD /mod=11 /x87=0E ; ST6 DD /mod=11 /x87=0F ; ST7 X87 DF /mod=11 /x87=08 ; ST0 DF /mod=11 /x87=09 ; ST1 DF /mod=11 /x87=0A ; ST2 DF /mod=11 /x87=0B ; ST3 DF /mod=11 /x87=0C ; ST4 DF /mod=11 /x87=0D ; ST5 DF /mod=11 /x87=0E ; ST6 DF /mod=11 /x87=0F ; ST7 X87 aso rexw rexr rexx rexb ; 0F AE /1 ; M aso rexw rexr rexx rexb ; 0F AE /0 ; M D9 /mod=11 /x87=34 ; X87 D9 /mod=11 /x87=31 ; X87 D9 /mod=11 /x87=39 ; X87 aso rexr rexx rexb ; sse66 0f 7c ; V W aso rexr rexx rexb ; ssef2 0f 7c ; V W f4 ; aso rexr rexx rexb ; sse66 0f 7d ; V W aso rexr rexx rexb ; ssef2 0f 7d ; V W aso oso rexw rexr rexx rexb ; F7 /7 ; Ev aso rexw rexr rexx rexb ; F6 /7 ; Eb ; e4 ; AL Ib oso ; e5 ; eAX Ib ec ; AL DX oso ; ed ; eAX DX aso oso rexw rexr rexx rexb ; 0f af ; Gv Ev aso rexw rexr rexx rexb ; F6 /5 ; Eb aso oso rexw rexr rexx rexb ; F7 /5 ; Ev aso oso rexw rexr rexx rexb ; 69 ; Gv Ev Iz aso oso rexw rexr rexx rexb ; 6b ; Gv Ev Ib oso ; 40 ; eAX oso ; 41 ; eCX oso ; 42 ; eDX oso ; 43 ; eBX oso ; 44 ; eSP oso ; 45 ; eBP oso ; 46 ; eSI oso ; 47 ; eDI aso oso rexw rexr rexx rexb ; FF /0 ; Ev aso rexw rexr rexx rexb ; FE /0 ; Eb ; 6c ; oso ; 6d /O16 ; oso ; 6d /O32 ; f1 ; ; cc ; ; cd ; Ib ; ce ; 0f 08 ; sse66 0f 38 80 /M32 ; Gd Mo sse66 0f 38 80 /M64 ; Gq Mo INTEL aso rexr rexx rexb ; 0F 01 /7 /mod=!11 ; M 0F 01 /3 /mod=11 /rm=7 ; AMD sse66 0f 38 81 /M32 ; Gd Mo sse66 0f 38 81 /M64 ; Gq Mo INTEL oso rexw ; cf /O16 ; oso rexw ; cf /O32 ; oso rexw ; cf /O64 ; ; 70 ; Jb oso ; 0f 80 ; Jz ; 71 ; Jb oso ; 0f 81 ; Jz ; 72 ; Jb oso ; 0f 82 ; Jz ; 73 ; Jb oso ; 0f 83 ; Jz ; 74 ; Jb oso ; 0f 84 ; Jz ; 75 ; Jb oso ; 0f 85 ; Jz ; 76 ; Jb oso ; 0f 86 ; Jz ; 77 ; Jb oso ; 0f 87 ; Jz ; 78 ; Jb oso ; 0f 88 ; Jz ; 79 ; Jb oso ; 0f 89 ; Jz ; 7a ; Jb oso ; 0f 8a ; Jz ; 7b ; Jb oso ; 0f 8b ; Jz ; 7c ; Jb oso ; 0f 8c ; Jz ; 7d ; Jb oso ; 0f 8d ; Jz ; 7e ; Jb oso ; 0f 8e ; Jz ; 7f ; Jb oso ; 0f 8f ; Jz aso ; e3 /A16 ; Jb aso ; e3 /A32 ; Jb aso ; e3 /A64 ; Jb aso oso rexw rexr rexx rexb ; FF /4 ; Ev aso oso rexw rexr rexx rexb ; FF /5 ; Ep oso ; e9 ; Jz ea ; Ap eb ; Jb ; 9f ; aso oso rexw rexr rexx rexb ; 0f 02 ; Gv Ew aso rexr rexx rexb ; ssef2 0f f0 ; V M aso rexw rexr rexx rexb ; 0F AE /2 ; Md aso oso ; c5 ; Gv M aso oso rexw rexr rexx rexb ; 8d ; Gv M aso oso ; c4 ; Gv M aso oso rexw rexr rexx rexb ; 0f b4 ; Gz M aso oso rexw rexr rexx rexb ; 0f b5 ; Gz M aso rexr rexx rexb ; 0F 01 /3 /mod=!11 ; M aso oso rexw rexr rexx rexb ; 0f b2 ; Gz M ; c9 ; 0F AE /5 /mod=11 /rm=0 ; 0F AE /5 /mod=11 /rm=1 ; 0F AE /5 /mod=11 /rm=2 ; 0F AE /5 /mod=11 /rm=3 ; 0F AE /5 /mod=11 /rm=4 ; 0F AE /5 /mod=11 /rm=5 ; 0F AE /5 /mod=11 /rm=6 ; 0F AE /5 /mod=11 /rm=7 ; aso rexr rexx rexb ; 0F 01 /2 /mod=!11 ; M aso rexr rexx rexb ; 0F 00 /2 ; Ew aso rexr rexx rexb ; 0F 01 /6 /mod=!11 ; Ew f0 ; ; ac ; oso rexw ; ad /O16 ; oso rexw ; ad /O32 ; oso rexw ; ad /O64 ; ; e0 ; Jb ; e1 ; Jb ; e2 ; Jb def64 depM aso oso rexw rexr rexx rexb ; 0f 03 ; Gv Ew aso rexr rexx rexb ; 0F 00 /3 ; Ew aso rexr rexx rexb ; 0f f7 ; P Q aso rexr rexx rexb ; sse66 0f f7 ; V W aso rexr rexx rexb ; sse66 0f 5f ; V W aso rexr rexx rexb ; 0f 5f ; V W aso rexr rexx rexb ; ssef2 0f 5f ; V W aso rexr rexx rexb ; ssef3 0f 5f ; V W 0F AE /6 /mod=11 /rm=0 ; 0F AE /6 /mod=11 /rm=1 ; 0F AE /6 /mod=11 /rm=2 ; 0F AE /6 /mod=11 /rm=3 ; 0F AE /6 /mod=11 /rm=4 ; 0F AE /6 /mod=11 /rm=5 ; 0F AE /6 /mod=11 /rm=6 ; 0F AE /6 /mod=11 /rm=7 ; aso rexr rexx rexb ; sse66 0f 5d ; V W aso rexr rexx rexb ; 0f 5d ; V W aso rexr rexx rexb ; ssef2 0f 5d ; V W aso rexr rexx rexb ; ssef3 0f 5d ; V W 0F 01 /1 /mod=11 /rm=0 ; ; 0f a6 /mod=11 /rm=0 /0 ; aso rexw rexr rexx rexb ; C6 /0 ; Eb Ib aso oso rexw rexr rexx rexb ; C7 /0 ; Ev Iz aso rexr rexx rexb ; 88 ; Eb Gb aso oso rexw rexr rexx rexb ; 89 ; Ev Gv aso rexr rexx rexb ; 8a ; Gb Eb aso oso rexw rexr rexx rexb ; 8b ; Gv Ev aso oso rexr rexx rexb ; 8c ; Ev S aso oso rexr rexx rexb ; 8e ; S Ev a0 ; AL Ob aso oso rexw ; a1 ; rAX Ov a2 ; Ob AL aso oso rexw ; a3 ; Ov rAX rexb ; b0 ; ALr8b Ib rexb ; b1 ; CLr9b Ib rexb ; b2 ; DLr10b Ib rexb ; b3 ; BLr11b Ib rexb ; b4 ; AHr12b Ib rexb ; b5 ; CHr13b Ib rexb ; b6 ; DHr14b Ib rexb ; b7 ; BHr15b Ib oso rexw rexb ; b8 ; rAXr8 Iv oso rexw rexb ; b9 ; rCXr9 Iv oso rexw rexb ; ba ; rDXr10 Iv oso rexw rexb ; bb ; rBXr11 Iv oso rexw rexb ; bc ; rSPr12 Iv oso rexw rexb ; bd ; rBPr13 Iv oso rexw rexb ; be ; rSIr14 Iv oso rexw rexb ; bf ; rDIr15 Iv rexr ; 0f 20 ; R C rexr ; 0f 21 ; R D rexr ; 0f 22 ; C R rexr ; 0f 23 ; D R aso rexr rexx rexb ; sse66 0f 28 ; V W aso rexr rexx rexb ; sse66 0f 29 ; W V aso rexr rexx rexb ; 0f 28 ; V W aso rexr rexx rexb ; 0f 29 ; W V aso rexw rexr rexx rexb ; sse66 0f 6e ; V Ex aso rexr rexx rexb ; 0f 6e ; P Ex aso rexw rexr rexx rexb ; sse66 0f 7e ; Ex V aso rexr rexx rexb ; 0f 7e ; Ex P aso rexr rexx rexb ; ssef2 0f 12 ; V W aso rexr rexx rexb ; sse66 0f 7f ; W V aso rexr rexx rexb ; ssef3 0f 6f ; V W aso rexr rexx rexb ; ssef3 0f 7f ; W V aso rexb ; ssef2 0f d6 ; P VR aso rexr rexx rexb ; sse66 0f 16 ; V M aso rexr rexx rexb ; sse66 0f 17 ; M V aso rexr rexx rexb ; 0f 16 ; V W aso rexr rexx rexb ; 0f 17 ; M V aso rexr rexx rexb ; sse66 0f 12 ; V M aso rexr rexx rexb ; sse66 0f 13 ; M V aso rexr rexx rexb ; 0f 12 ; V W aso rexr rexx rexb ; 0f 13 ; M V oso rexr rexb ; sse66 0f 50 ; Gd VR oso rexr rexb ; 0f 50 ; Gd VR aso rexr rexx rexb ; sse66 0f e7 ; M V aso rexw rexr rexx rexb ; 0f c3 ; M Gvw aso rexr rexx rexb ; sse66 0f 2b ; M V aso rexr rexx rexb ; 0f 2b ; M V 0f e7 ; M P aso rexr rexx rexb ; 0f 6f ; P Q aso rexr rexx rexb ; sse66 0f d6 ; W V aso rexr rexx rexb ; ssef3 0f 7e ; V W aso rexr rexx rexb ; 0f 7f ; Q P aso rexr rexx rexb ; sse66 0f 6f ; V W aso ; ssef3 0f d6 ; V PR a4 ; oso rexw ; a5 /O16 ; oso rexw ; a5 /O32 ; aso rexr rexx rexb ; ssef2 0f 10 ; V W aso rexr rexx rexb ; ssef2 0f 11 ; W V oso rexw ; a5 /O64 ; aso rexr rexx rexb ; ssef3 0f 12 ; V W aso rexr rexx rexb ; ssef3 0f 16 ; V W aso rexr rexx rexb ; ssef3 0f 10 ; V W aso rexr rexx rexb ; ssef3 0f 11 ; W V aso oso rexw rexr rexx rexb ; 0f be ; Gv Eb aso oso rexw rexr rexx rexb ; 0f bf ; Gv Ew aso rexr rexx rexb ; sse66 0f 10 ; V W aso rexr rexx rexb ; sse66 0f 11 ; W V aso rexr rexx rexb ; 0f 10 ; V W aso rexr rexx rexb ; 0f 11 ; W V aso oso rexw rexr rexx rexb ; 0f b6 ; Gv Eb aso oso rexw rexr rexx rexb ; 0f b7 ; Gv Ew aso rexw rexr rexx rexb ; F6 /4 ; Eb aso oso rexw rexr rexx rexb ; F7 /4 ; Ev aso rexr rexx rexb ; sse66 0f 59 ; V W aso rexr rexx rexb ; 0f 59 ; V W aso rexr rexx rexb ; ssef2 0f 59 ; V W aso rexr rexx rexb ; ssef3 0f 59 ; V W 0F 01 /1 /mod=11 /rm=1 ; aso rexw rexr rexx rexb ; F6 /3 ; Eb aso oso rexw rexr rexx rexb ; F7 /3 ; Ev ; 90 ; aso rexr rexx rexb ; 0f 19 ; M aso rexr rexx rexb ; 0f 1a ; M aso rexr rexx rexb ; 0f 1b ; M aso rexr rexx rexb ; 0f 1c ; M aso rexr rexx rexb ; 0f 1d ; M aso rexr rexx rexb ; 0f 1e ; M aso rexr rexx rexb ; 0f 1f ; M aso rexw rexr rexx rexb ; F6 /2 ; Eb aso oso rexw rexr rexx rexb ; F7 /2 ; Ev aso rexr rexx rexb ; 08 ; Eb Gb aso oso rexw rexr rexx rexb ; 09 ; Ev Gv aso rexr rexx rexb ; 0a ; Gb Eb aso oso rexw rexr rexx rexb ; 0b ; Gv Ev ; 0c ; AL Ib oso rexw ; 0d ; rAX Iz aso rexr rexx rexb ; 80 /1 ; Eb Ib aso oso rexw rexr rexx rexb ; 81 /1 ; Ev Iz aso rexr rexx rexb ; 82 /1 ; Eb Ib aso oso rexw rexr rexx rexb ; 83 /1 ; Ev Ib aso rexr rexx rexb ; sse66 0f 56 ; V W aso rexr rexx rexb ; 0f 56 ; V W ; e6 ; Ib AL oso ; e7 ; Ib eAX ; ee ; DX AL oso ; ef ; DX eAX 6e ; oso ; 6f /o16 ; oso ; 6f /o32 ; oso ; 6f /o64; aso rexr rexx rexb ; sse66 0f 63 ; V W aso rexr rexx rexb ; 0f 63 ; P Q aso rexr rexx rexb ; sse66 0f 6b ; V W aso rexr rexx rexb ; 0f 6b ; P Q aso rexr rexx rexb ; sse66 0f 67 ; V W aso rexr rexx rexb ; 0f 67 ; P Q aso rexr rexx rexb ; sse66 0f fc ; V W aso rexr rexx rexb ; 0f fc ; P Q aso rexr rexx rexb ; 0f fd ; P Q aso rexr rexx rexb ; sse66 0f fd ; V W aso rexr rexx rexb ; 0f d4 ; P Q aso rexr rexx rexb ; sse66 0f d4 ; V W aso rexr rexx rexb ; 0f ec ; P Q aso rexr rexx rexb ; sse66 0f ec ; V W aso rexr rexx rexb ; 0f ed ; P Q aso rexr rexx rexb ; sse66 0f ed ; V W aso rexr rexx rexb ; 0f dc ; P Q aso rexr rexx rexb ; 0f dd ; P Q aso rexr rexx rexb ; sse66 0f db ; V W aso rexr rexx rexb ; 0f db ; P Q aso rexr rexx rexb ; sse66 0f df ; V W aso rexr rexx rexb ; 0f df ; P Q ; f3 90 ; aso rexr rexx rexb ; sse66 0f e0 ; V W aso rexr rexx rexb ; 0f e0 ; P Q aso rexr rexx rexb ; sse66 0f e3 ; V W aso rexr rexx rexb ; 0f e3 ; P Q aso rexr rexx rexb ; 0f 74 ; P Q aso rexr rexx rexb ; sse66 0f 74 ; V W aso rexr rexx rexb ; 0f 75 ; P Q aso rexr rexx rexb ; sse66 0f 75 ; V W aso rexr rexx rexb ; 0f 76 ; P Q aso rexr rexx rexb ; sse66 0f 76 ; V W aso rexr rexx rexb ; sse66 0f 64 ; V W aso rexr rexx rexb ; 0f 64 ; P Q aso rexr rexx rexb ; sse66 0f 65 ; V W aso rexr rexx rexb ; 0f 65 ; P Q aso rexr rexx rexb ; sse66 0f 66 ; V W aso rexr rexx rexb ; 0f 66 ; P Q aso rexr rexb ; sse66 0f c5 ; Gd VR Ib aso oso rexw rexr rexx rexb ; 0f c5 ; Gd PR Ib aso oso rexw rexr rexx rexb ; 0f c4 ; P Ew Ib aso rexw rexr rexx rexb ; sse66 0f c4 ; V Ew Ib aso rexr rexx rexb ; 0f f5 ; P Q aso rexr rexx rexb ; sse66 0f f5 ; V W aso rexr rexx rexb ; sse66 0f ee ; V W aso rexr rexx rexb ; 0f ee ; P Q aso rexr rexx rexb ; 0f de ; P Q aso rexr rexx rexb ; sse66 0f de ; V W aso rexr rexx rexb ; sse66 0f ea ; V W aso rexr rexx rexb ; 0f ea ; P Q aso rexr rexx rexb ; sse66 0f da ; V W aso rexr rexx rexb ; 0f da ; P Q rexr rexb ; sse66 0f d7 ; Gd VR oso rexr rexb ; 0f d7 ; Gd PR aso rexr rexx rexb ; 0f e4 ; P Q aso rexr rexx rexb ; sse66 0f e4 ; V W aso rexr rexx rexb ; sse66 0f e5 ; V W aso rexr rexx rexb ; 0f e5 ; P Q aso rexr rexx rexb ; 0f d5 ; P Q aso rexr rexx rexb ; sse66 0f d5 ; V W aso rexr rexx rexb ; 0f f4 ; P Q aso rexr rexx rexb ; sse66 0f f4 ; V W ; 07 ; ES ; 17 ; SS ; 1f ; DS 0f a9 ; GS 0f a1 ; FS oso rexb ; 58 ; rAXr8 oso rexb ; 59 ; rCXr9 oso rexb ; 5A ; rDXr10 oso rexb ; 5B ; rBXr11 oso rexb ; 5C ; rSPr12 oso rexb ; 5D ; rBPr13 oso rexb ; 5E ; rSIr14 oso rexb ; 5F ; rDIr15 aso oso rexw rexr rexx rexb ; 8F /0 ; Ev oso ; 61 /O16 ; oso ; 61 /O32 ; oso ; 9d /M32 /O16 ; oso ; 9d /M16 /O16 ; oso ; 9d /M16 /O32 ; oso ; 9d /M32 /O32 ; oso ; 9d /M64 ; aso rexr rexx rexb ; sse66 0f eb ; V W aso rexr rexx rexb ; 0f eb ; P Q aso rexw rexr rexx rexb ; 0F 0D /0 ; M aso rexw rexr rexx rexb ; 0F 0D /1 ; M aso rexw rexr rexx rexb ; 0F 0D /2 ; M aso rexw rexr rexx rexb ; 0F 0D /3 ; M aso rexw rexr rexx rexb ; 0F 0D /4 ; M aso rexw rexr rexx rexb ; 0F 0D /5 ; M aso rexw rexr rexx rexb ; 0F 0D /6 ; M aso rexw rexr rexx rexb ; 0F 0D /7 ; M aso rexw rexr rexx rexb ; 0F 18 /0 ; M aso rexw rexr rexx rexb ; 0F 18 /1 ; M aso rexw rexr rexx rexb ; 0F 18 /2 ; M aso rexw rexr rexx rexb ; 0F 18 /3 ; M aso rexr rexx rexb ; sse66 0f f6 ; V W aso rexr rexx rexb ; 0f f6 ; P Q aso rexr rexx rexb ; sse66 0f 70 ; V W Ib aso rexr rexx rexb ; ssef3 0f 70 ; V W Ib aso rexr rexx rexb ; ssef2 0f 70 ; V W Ib aso rexr rexx rexb ; 0f 70 ; P Q Ib rexb ; sse66 0F 73 /7 ; VR Ib aso rexr rexx rexb ; sse66 0f f1 ; V W aso rexr rexx rexb ; 0f f1 ; P Q rexb ; sse66 0F 71 /6 ; VR Ib 0F 71 /6 ; PR Ib aso rexr rexx rexb ; sse66 0f f2 ; V W aso rexr rexx rexb ; 0f f2 ; P Q rexb ; sse66 0F 72 /6 ; VR Ib 0F 72 /6 ; PR Ib aso rexr rexx rexb ; sse66 0f f3 ; V W aso rexr rexx rexb ; 0f f3 ; P Q rexb ; sse66 0F 73 /6 ; VR Ib 0F 73 /6 ; PR Ib aso rexr rexx rexb ; 0f e1 ; P Q aso rexr rexx rexb ; sse66 0f e1 ; V W rexb ; sse66 0F 71 /4 ; VR Ib 0F 71 /4 ; PR Ib 0F 72 /4 ; PR Ib aso rexr rexx rexb ; sse66 0f e2 ; V W aso rexr rexx rexb ; 0f e2 ; P Q rexb ; sse66 0F 72 /4 ; VR Ib 0F 71 /2 ; PR Ib aso rexr rexx rexb ; 0f d1 ; P Q aso rexr rexx rexb ; sse66 0f d1 ; V W rexb ; sse66 0F 71 /2 ; VR Ib 0F 72 /2 ; PR Ib aso rexr rexx rexb ; 0f d2 ; P Q aso rexr rexx rexb ; sse66 0f d2 ; V W rexb ; sse66 0F 72 /2 ; VR Ib 0F 73 /2 ; PR Ib aso rexr rexx rexb ; 0f d3 ; P Q aso rexr rexx rexb ; sse66 0f d3 ; V W rexb ; sse66 0F 73 /2 ; VR Ib rexb ; sse66 0F 73 /3 ; VR Ib aso rexr rexx rexb ; sse66 0f f8 ; V W aso rexr rexx rexb ; 0f f8 ; P Q aso rexr rexx rexb ; sse66 0f f9 ; V W aso rexr rexx rexb ; 0f f9 ; P Q aso rexr rexx rexb ; 0f fa ; P Q aso rexr rexx rexb ; sse66 0f fa ; V W aso rexr rexx rexb ; sse66 0f fb ; V W aso rexr rexx rexb ; 0f fb ; P Q aso rexr rexx rexb ; 0f e8 ; P Q aso rexr rexx rexb ; sse66 0f e8 ; V W aso rexr rexx rexb ; 0f e9 ; P Q aso rexr rexx rexb ; sse66 0f e9 ; V W aso rexr rexx rexb ; 0f d8 ; P Q aso rexr rexx rexb ; sse66 0f d8 ; V W aso rexr rexx rexb ; sse66 0f dc ; V W aso rexr rexx rexb ; 0f d9 ; P Q aso rexr rexx rexb ; sse66 0f d9 ; V W aso rexr rexx rexb ; sse66 0f 68 ; V W aso rexr rexx rexb ; sse66 0f dd ; V W aso rexr rexx rexb ; 0f 68 ; P Q aso rexr rexx rexb ; sse66 0f 69 ; V W aso rexr rexx rexb ; 0f 69 ; P Q aso rexr rexx rexb ; sse66 0f 6a ; V W aso rexr rexx rexb ; 0f 6a ; P Q aso rexr rexx rexb ; sse66 0f 6d ; V W aso rexr rexx rexb ; sse66 0f 60 ; V W aso rexr rexx rexb ; 0f 60 ; P Q aso rexr rexx rexb ; sse66 0f 61 ; V W aso rexr rexx rexb ; 0f 61 ; P Q aso rexr rexx rexb ; sse66 0f 62 ; V W aso rexr rexx rexb ; 0f 62 ; P Q aso rexr rexx rexb ; sse66 0f 6c ; V W ; 0f 0f /3dnow=0C ; P Q ; 0f 0f /3dnow=0D ; P Q ; 0f 0f /3dnow=1C ; P Q ; 0f 0f /3dnow=1D ; P Q ; 0f 0f /3dnow=8A ; P Q ; 0f 0f /3dnow=8E ; P Q ; 0f 0f /3dnow=90 ; P Q ; 0f 0f /3dnow=94 ; P Q ; 0f 0f /3dnow=96 ; P Q ; 0f 0f /3dnow=97 ; P Q ; 0f 0f /3dnow=9A ; P Q ; 0f 0f /3dnow=9E ; P Q ; 0f 0f /3dnow=A0 ; P Q ; 0f 0f /3dnow=A4 ; P Q ; 0f 0f /3dnow=A6 ; P Q ; 0f 0f /3dnow=A7 ; P Q ; 0f 0f /3dnow=AA ; P Q ; 0f 0f /3dnow=AE ; P Q ; 0f 0f /3dnow=B0 ; P Q ; 0f 0f /3dnow=B4 ; P Q ; 0f 0f /3dnow=B6 ; P Q ; 0f 0f /3dnow=B7 ; P Q ; 0f 0f /3dnow=BB ; P Q ; 0f 0f /3dnow=BF ; P Q ; 06 ; ES ; 0e ; CS ; 16 ; SS ; 1e ; DS ; 0f a8 ; GS ; 0f a0 ; FS oso rexb ; 50 ; rAXr8 oso rexb ; 51 ; rCXr9 oso rexb ; 52 ; rDXr10 oso rexb ; 53 ; rBXr11 oso rexb ; 54 ; rSPr12 oso rexb ; 55 ; rBPr13 oso rexb ; 56 ; rSIr14 oso rexb ; 57 ; rDIr15 oso ; 68 ; Iz aso oso rexw rexr rexx rexb ; FF /6 ; Ev ; 6a ; Ib oso ; 60 /O16 ; oso ; 60 /O32 ; oso ; 9c /M32 /O16 ; oso ; 9c /M16 /O16 ; oso rexw ; 9c /M64 /O16 ; oso ; 9c /M16 /O32 ; oso ; 9c /M32 /O32 ; oso rexw ; 9c /M64 /O32 ; oso rexw ; 9c /M64 /O64 ; aso rexr rexx rexb ; sse66 0f ef ; V W aso rexr rexx rexb ; 0f ef ; P Q aso rexw rexr rexx rexb ; C0 /2 ; Eb Ib aso oso rexw rexr rexx rexb ; C1 /2 ; Ev Ib aso rexw rexr rexx rexb ; D0 /2 ; Eb I1 aso rexw rexr rexx rexb ; D2 /2 ; Eb CL aso oso rexw rexr rexx rexb ; D3 /2 ; Ev CL aso oso rexw rexr rexx rexb ; D1 /2 ; Ev I1 aso rexw rexr rexx rexb ; D0 /3 ; Eb I1 aso oso rexw rexr rexx rexb ; C1 /3 ; Ev Ib aso rexw rexr rexx rexb ; C0 /3 ; Eb Ib aso oso rexw rexr rexx rexb ; D1 /3 ; Ev I1 aso rexw rexr rexx rexb ; D2 /3 ; Eb CL aso oso rexw rexr rexx rexb ; D3 /3 ; Ev CL aso rexw rexr rexx rexb ; C0 /0 ; Eb Ib aso rexw rexr rexx rexb ; D0 /0 ; Eb I1 aso oso rexw rexr rexx rexb ; D1 /0 ; Ev I1 aso rexw rexr rexx rexb ; D2 /0 ; Eb CL aso oso rexw rexr rexx rexb ; D3 /0 ; Ev CL aso oso rexw rexr rexx rexb ; C1 /0 ; Ev Ib aso rexw rexr rexx rexb ; D0 /1 ; Eb I1 aso rexw rexr rexx rexb ; C0 /1 ; Eb Ib aso oso rexw rexr rexx rexb ; C1 /1 ; Ev Ib aso oso rexw rexr rexx rexb ; D1 /1 ; Ev I1 aso rexw rexr rexx rexb ; D2 /1 ; Eb CL aso oso rexw rexr rexx rexb ; D3 /1 ; Ev CL aso rexr rexx rexb ; 0f 53 ; V W aso rexr rexx rexb ; ssef3 0f 53 ; V W 0f 32 ; 0f 33 ; 0f 31 ; 0F 01 /7 /mod=11 /rm=1 ; AMD f2 ; f3 ; ; c2 ; Iw ; c3 ; ; ca ; Iw ; cb ; 0f aa ; aso rexr rexx rexb ; 0f 52 ; V W aso rexr rexx rexb ; ssef3 0f 52 ; V W ; 9e ; ; d6 ; aso oso rexw rexr rexx rexb ; D1 /7 ; Ev I1 aso rexw rexr rexx rexb ; C0 /7 ; Eb Ib aso rexw rexr rexx rexb ; D0 /7 ; Eb I1 aso oso rexw rexr rexx rexb ; C1 /7 ; Ev Ib aso rexw rexr rexx rexb ; D2 /7 ; Eb CL aso oso rexw rexr rexx rexb ; D3 /7 ; Ev CL aso rexw rexr rexx rexb ; C0 /6 ; Eb Ib aso oso rexw rexr rexx rexb ; C1 /6 ; Ev Ib aso rexw rexr rexx rexb ; D0 /6 ; Eb I1 aso rexw rexr rexx rexb ; D2 /6 ; Eb CL aso oso rexw rexr rexx rexb ; D3 /6 ; Ev CL aso oso rexw rexr rexx rexb ; C1 /4 ; Ev Ib aso rexr rexx rexb ; D2 /4 ; Eb CL aso oso rexw rexr rexx rexb ; D1 /4 ; Ev I1 aso rexw rexr rexx rexb ; D0 /4 ; Eb I1 aso rexw rexr rexx rexb ; C0 /4 ; Eb Ib aso oso rexw rexr rexx rexb ; D3 /4 ; Ev CL aso oso rexw rexr rexx rexb ; D1 /6 ; Ev I1 aso oso rexw rexr rexx rexb ; C1 /5 ; Ev Ib aso rexw rexr rexx rexb ; D2 /5 ; Eb CL aso oso rexw rexr rexx rexb ; D1 /5 ; Ev I1 aso rexw rexr rexx rexb ; D0 /5 ; Eb I1 aso rexw rexr rexx rexb ; C0 /5 ; Eb Ib aso oso rexw rexr rexx rexb ; D3 /5 ; Ev CL aso rexr rexx rexb ; 18 ; Eb Gb aso oso rexw rexr rexx rexb ; 19 ; Ev Gv aso rexr rexx rexb ; 1a ; Gb Eb aso oso rexw rexr rexx rexb ; 1b ; Gv Ev ; 1c ; AL Ib oso rexw ; 1d ; rAX Iz aso rexr rexx rexb ; 80 /3 ; Eb Ib aso oso rexw rexr rexx rexb ; 81 /3 ; Ev Iz aso rexr rexx rexb ; 82 /3 ; Eb Ib aso oso rexw rexr rexx rexb ; 83 /3 ; Ev Ib ; ae ; oso rexw ; af /O16 ; oso rexw ; af /O32 ; oso rexw ; af /O64 ; aso rexr rexx rexb ; 0f 90 ; Eb aso rexr rexx rexb ; 0f 91 ; Eb aso rexr rexx rexb ; 0f 92 ; Eb aso rexr rexx rexb ; 0f 93 ; Eb aso rexr rexx rexb ; 0f 94 ; Eb aso rexr rexx rexb ; 0f 95 ; Eb aso rexr rexx rexb ; 0f 96 ; Eb aso rexr rexx rexb ; 0f 97 ; Eb aso rexr rexx rexb ; 0f 98 ; Eb aso rexr rexx rexb ; 0f 99 ; Eb aso rexr rexx rexb ; 0f 9a ; Eb aso rexr rexx rexb ; 0f 9b ; Eb aso rexr rexx rexb ; 0f 9c ; Eb aso rexr rexx rexb ; 0f 9d ; Eb aso rexr rexx rexb ; 0f 9e ; Eb aso rexr rexx rexb ; 0f 9f ; Eb 0F AE /7 /mod=11 /rm=0 ; 0F AE /7 /mod=11 /rm=1 ; 0F AE /7 /mod=11 /rm=2 ; 0F AE /7 /mod=11 /rm=3 ; 0F AE /7 /mod=11 /rm=4 ; 0F AE /7 /mod=11 /rm=5 ; 0F AE /7 /mod=11 /rm=6 ; 0F AE /7 /mod=11 /rm=7 ; aso rexr rexx rexb ; 0F 01 /0 /mod=!11 ; M aso oso rexw rexr rexx rexb ; 0f a4 ; Ev Gv Ib aso oso rexw rexr rexx rexb ; 0f a5 ; Ev Gv CL aso oso rexw rexr rexx rexb ; 0f ac ; Ev Gv Ib aso oso rexw rexr rexx rexb ; 0f ad ; Ev Gv CL aso rexr rexx rexb ; sse66 0f c6 ; V W Ib aso rexr rexx rexb ; 0f c6 ; V W Ib aso rexr rexx rexb ; 0F 01 /1 /mod=!11 ; M aso oso rexr rexx rexb ; 0F 00 /0 ; Ev aso rexr rexx rexb ; 0F 01 /4 /mod=!11 ; M aso rexr rexx rexb ; 0f 51 ; V W aso rexr rexx rexb ; sse66 0f 51 ; V W aso rexr rexx rexb ; ssef2 0f 51 ; V W aso rexr rexx rexb ; ssef3 0f 51 ; V W f9 ; fd ; 0F 01 /3 /mod=11 /rm=4 ; AMD fb ; 0F 01 /3 /mod=11 /rm=6 ; AMD aso rexw rexr rexx rexb ; 0F AE /3 ; Md ; aa ; oso rexw ; ab /O16 ; oso rexw ; ab /O32 ; oso rexw ; ab /O64 ; aso oso rexr rexx rexb ; 0F 00 /1 ; Ev aso rexr rexx rexb ; 28 ; Eb Gb aso oso rexw rexr rexx rexb ; 29 ; Ev Gv aso rexr rexx rexb ; 2a ; Gb Eb aso oso rexw rexr rexx rexb ; 2b ; Gv Ev 2c ; AL Ib oso rexw ; 2d ; rAX Iz aso rexr rexx rexb ; 80 /5 ; Eb Ib aso oso rexw rexr rexx rexb ; 81 /5 ; Ev Iz aso rexr rexx rexb ; 82 /5 ; Eb Ib aso oso rexw rexr rexx rexb ; 83 /5 ; Ev Ib aso rexr rexx rexb ; sse66 0f 5c ; V W aso rexr rexx rexb ; 0f 5c ; V W aso rexr rexx rexb ; ssef2 0f 5c ; V W aso rexr rexx rexb ; ssef3 0f 5c ; V W 0F 01 /7 /mod=11 /rm=0 ; 0f 05 ; 0f 34 ; 0f 35 ; 0f 07 ; aso rexw rexr rexx rexb ; F6 /0 ; Eb Ib aso rexr rexx rexb ; 84 ; Eb Gb aso oso rexw rexr rexx rexb ; 85 ; Ev Gv a8 ; AL Ib oso rexw ; a9 ; rAX Iz aso rexw rexr rexx rexb ; F6 /1 ; Eb Ib aso oso rexw rexr rexx rexb ; F7 /0 ; Ev Iz aso oso rexw rexr rexx rexb ; F7 /1 ; Ev Iz aso rexr rexx rexb ; sse66 0f 2e ; V W aso rexr rexx rexb ; 0f 2e ; V W 0f 0b ; aso rexr rexx rexb ; sse66 0f 15 ; V W aso rexr rexx rexb ; 0f 15 ; V W aso rexr rexx rexb ; 0f 14 ; V W aso rexr rexx rexb ; sse66 0f 14 ; V W aso rexr rexx rexb ; 0F 00 /4 ; Ew aso rexr rexx rexb ; 0F 00 /5 ; Ew 0F 01 /0 /mod=11 /rm=1 ; INTEL aso rexr rexx rexb ; sse66 0F C7 /6 ; Mq INTEL aso rexr rexx rexb ; ssef3 0F C7 /6 ; Mq INTEL aso rexr rexx rexb ; 0F C7 /6 ; Mq INTEL aso rexr rexx rexb ; 0F C7 /7 ; Mq INTEL 0F 01 /0 /mod=11 /rm=2 ; INTEL 0F 01 /0 /mod=11 /rm=3 ; INTEL 0F 01 /0 /mod=11 /rm=4 ; INTEL aso rexr rexx rexb ; 0F 78 /M16 ; Ed Gd aso rexr rexx rexb ; 0F 78 /M32 ; Ed Gd aso rexr rexx rexb ; 0F 78 /M64 ; Eq Gq INTEL aso rexr rexx rexb ; 0F 79 /M16 ; Gd Ed aso rexr rexx rexb ; 0F 79 /M32 ; Gd Ed aso rexr rexx rexb ; 0F 79 /M64 ; Gq Eq INTEL 0F 01 /3 /mod=11 /rm=0 ; AMD 0F 01 /3 /mod=11 /rm=1 ; AMD 0F 01 /3 /mod=11 /rm=2 ; AMD 0F 01 /3 /mod=11 /rm=3 ; AMD ; 9b ; 0f 09 ; 0f 30 ; aso oso rexr rexx rexb ; 0f c0 ; Eb Gb aso oso rexw rexr rexx rexb ; sse66 0f c1 ; Ev Gv aso rexw rexr rexx rexb ; sse66 0f c0 ; Eb Gb aso rexw rexr rexx rexb ; ssef2 0f c0 ; Eb Gb aso oso rexr rexx rexb ; ssef2 0f c1 ; Ev Gv aso rexw rexr rexx rexb ; ssef3 0f c0 ; Eb Gb aso rexw rexr rexx rexb ; ssef3 0f c1 ; Ev Gv aso oso rexw rexr rexx rexb ; 0f c1 ; Ev Gv aso rexr rexx rexb ; 86 ; Eb Gb aso oso rexw rexr rexx rexb ; 87 ; Ev Gv oso rexw rexb ; 90 ; rAXr8 rAX oso rexw rexb ; 91 ; rCXr9 rAX oso rexw rexb ; 92 ; rDXr10 rAX oso rexw rexb ; 93 ; rBXr11 rAX oso rexw rexb ; 94 ; rSPr12 rAX oso rexw rexb ; 95 ; rBPr13 rAX oso rexw rexb ; 96 ; rSIr14 rAX oso rexw rexb ; 97 ; rDIr15 rAX rexw ; d7 ; aso rexr rexx rexb ; 30 ; Eb Gb aso oso rexw rexr rexx rexb ; 31 ; Ev Gv aso rexr rexx rexb ; 32 ; Gb Eb aso oso rexw rexr rexx rexb ; 33 ; Gv Ev ; 34 ; AL Ib oso rexw ; 35 ; rAX Iz aso rexr rexx rexb ; 80 /6 ; Eb Ib aso oso rexw rexr rexx rexb ; 81 /6 ; Ev Iz aso rexr rexx rexb ; 82 /6 ; Eb Ib aso oso rexw rexr rexx rexb ; 83 /6 ; Ev Ib aso rexr rexx rexb ; sse66 0f 57 ; V W aso rexr rexx rexb ; 0f 57 ; V W ; 0f a7 /mod=11 /rm=0 /1 ; ; 0f a7 /mod=11 /rm=0 /2 ; ; 0f a7 /mod=11 /rm=0 /3 ; ; 0f a7 /mod=11 /rm=0 /4 ; ; 0f a7 /mod=11 /rm=0 /5 ; ; 0F 01 /2 /mod=11 /rm=0 ; ; 0F AE /5 /mod=!11 ; M ; 0F 01 /2 /mod=11 /rm=1 ; ; 0F AE /4 /mod=!11 ; M ; 0f a6 /mod=11 /rm=0 /1 ; ; 0f a6 /mod=11 /rm=0 /2 ; ; 0f a7 /mod=11 /rm=0 /0 ; ksplice-0.9.9/kmodsrc/x86/libudis86/input.c0000644000000000000000000001644611206570615017102 0ustar rootroot/* udis86 - libudis86/input.c * * Copyright (c) 2002-2009 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "extern.h" #include "types.h" #include "input.h" /* ----------------------------------------------------------------------------- * inp_buff_hook() - Hook for buffered inputs. * ----------------------------------------------------------------------------- */ static int inp_buff_hook(struct ud* u) { if (u->inp_buff < u->inp_buff_end) return *u->inp_buff++; else return -1; } #ifndef __UD_STANDALONE__ /* ----------------------------------------------------------------------------- * inp_file_hook() - Hook for FILE inputs. * ----------------------------------------------------------------------------- */ static int inp_file_hook(struct ud* u) { return fgetc(u->inp_file); } #endif /* __UD_STANDALONE__*/ /* ============================================================================= * ud_inp_set_hook() - Sets input hook. * ============================================================================= */ extern void ud_set_input_hook(register struct ud* u, int (*hook)(struct ud*)) { u->inp_hook = hook; inp_init(u); } extern void ud_set_user_opaque_data( struct ud * u, void * opaque ) { u->user_opaque_data = opaque; } extern void * ud_get_user_opaque_data( struct ud * u ) { return u->user_opaque_data; } /* ============================================================================= * ud_inp_set_buffer() - Set buffer as input. * ============================================================================= */ extern void ud_set_input_buffer(register struct ud* u, uint8_t* buf, size_t len) { u->inp_hook = inp_buff_hook; u->inp_buff = buf; u->inp_buff_end = buf + len; inp_init(u); } #ifndef __UD_STANDALONE__ /* ============================================================================= * ud_input_set_file() - Set buffer as input. * ============================================================================= */ extern void ud_set_input_file(register struct ud* u, FILE* f) { u->inp_hook = inp_file_hook; u->inp_file = f; inp_init(u); } #endif /* __UD_STANDALONE__ */ /* ============================================================================= * ud_input_skip() - Skip n input bytes. * ============================================================================= */ extern void ud_input_skip(struct ud* u, size_t n) { while (n--) { u->inp_hook(u); } } /* ============================================================================= * ud_input_end() - Test for end of input. * ============================================================================= */ extern int ud_input_end(struct ud* u) { return (u->inp_curr == u->inp_fill) && u->inp_end; } /* ----------------------------------------------------------------------------- * inp_next() - Loads and returns the next byte from input. * * inp_curr and inp_fill are pointers to the cache. The program is written based * on the property that they are 8-bits in size, and will eventually wrap around * forming a circular buffer. So, the size of the cache is 256 in size, kind of * unnecessary yet optimized. * * A buffer inp_sess stores the bytes disassembled for a single session. * ----------------------------------------------------------------------------- */ extern uint8_t inp_next(struct ud* u) { int c = -1; /* if current pointer is not upto the fill point in the * input cache. */ if ( u->inp_curr != u->inp_fill ) { c = u->inp_cache[ ++u->inp_curr ]; /* if !end-of-input, call the input hook and get a byte */ } else if ( u->inp_end || ( c = u->inp_hook( u ) ) == -1 ) { /* end-of-input, mark it as an error, since the decoder, * expected a byte more. */ u->error = 1; /* flag end of input */ u->inp_end = 1; return 0; } else { /* increment pointers, we have a new byte. */ u->inp_curr = ++u->inp_fill; /* add the byte to the cache */ u->inp_cache[ u->inp_fill ] = c; } /* record bytes input per decode-session. */ u->inp_sess[ u->inp_ctr++ ] = c; /* return byte */ return ( uint8_t ) c; } /* ----------------------------------------------------------------------------- * inp_back() - Move back a single byte in the stream. * ----------------------------------------------------------------------------- */ extern void inp_back(struct ud* u) { if ( u->inp_ctr > 0 ) { --u->inp_curr; --u->inp_ctr; } } /* ----------------------------------------------------------------------------- * inp_peek() - Peek into the next byte in source. * ----------------------------------------------------------------------------- */ extern uint8_t inp_peek(struct ud* u) { uint8_t r = inp_next(u); if ( !u->error ) inp_back(u); /* Don't backup if there was an error */ return r; } /* ----------------------------------------------------------------------------- * inp_move() - Move ahead n input bytes. * ----------------------------------------------------------------------------- */ extern void inp_move(struct ud* u, size_t n) { while (n--) inp_next(u); } /*------------------------------------------------------------------------------ * inp_uintN() - return uintN from source. *------------------------------------------------------------------------------ */ extern uint8_t inp_uint8(struct ud* u) { return inp_next(u); } extern uint16_t inp_uint16(struct ud* u) { uint16_t r, ret; ret = inp_next(u); r = inp_next(u); return ret | (r << 8); } extern uint32_t inp_uint32(struct ud* u) { uint32_t r, ret; ret = inp_next(u); r = inp_next(u); ret = ret | (r << 8); r = inp_next(u); ret = ret | (r << 16); r = inp_next(u); return ret | (r << 24); } extern uint64_t inp_uint64(struct ud* u) { uint64_t r, ret; ret = inp_next(u); r = inp_next(u); ret = ret | (r << 8); r = inp_next(u); ret = ret | (r << 16); r = inp_next(u); ret = ret | (r << 24); r = inp_next(u); ret = ret | (r << 32); r = inp_next(u); ret = ret | (r << 40); r = inp_next(u); ret = ret | (r << 48); r = inp_next(u); return ret | (r << 56); } ksplice-0.9.9/kmodsrc/x86/libudis86/itab.h0000644000000000000000000004415511244274432016665 0ustar rootroot /* itab.h -- auto generated by opgen.py, do not edit. */ #ifndef UD_ITAB_H #define UD_ITAB_H enum ud_itab_vendor_index { ITAB__VENDOR_INDX__AMD, ITAB__VENDOR_INDX__INTEL, ITAB__VENDOR_INDX__ANY, }; enum ud_itab_mode_index { ITAB__MODE_INDX__16, ITAB__MODE_INDX__32, ITAB__MODE_INDX__64 }; enum ud_itab_mod_index { ITAB__MOD_INDX__NOT_11, ITAB__MOD_INDX__11 }; enum ud_itab_index { ITAB__0F, ITAB__0F__OP_00__REG, ITAB__0F__OP_01__REG, ITAB__0F__OP_01__REG__OP_00__MOD, ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM, ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM__OP_01__VENDOR, ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM__OP_02__VENDOR, ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM__OP_03__VENDOR, ITAB__0F__OP_01__REG__OP_00__MOD__OP_01__RM__OP_04__VENDOR, ITAB__0F__OP_01__REG__OP_01__MOD, ITAB__0F__OP_01__REG__OP_01__MOD__OP_01__RM, ITAB__0F__OP_01__REG__OP_02__MOD, ITAB__0F__OP_01__REG__OP_02__MOD__OP_01__RM, ITAB__0F__OP_01__REG__OP_03__MOD, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_00__VENDOR, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_01__VENDOR, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_02__VENDOR, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_03__VENDOR, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_04__VENDOR, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_05__VENDOR, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_06__VENDOR, ITAB__0F__OP_01__REG__OP_03__MOD__OP_01__RM__OP_07__VENDOR, ITAB__0F__OP_01__REG__OP_04__MOD, ITAB__0F__OP_01__REG__OP_06__MOD, ITAB__0F__OP_01__REG__OP_07__MOD, ITAB__0F__OP_01__REG__OP_07__MOD__OP_01__RM, ITAB__0F__OP_01__REG__OP_07__MOD__OP_01__RM__OP_01__VENDOR, ITAB__0F__OP_0D__REG, ITAB__0F__OP_18__REG, ITAB__0F__OP_71__REG, ITAB__0F__OP_72__REG, ITAB__0F__OP_73__REG, ITAB__0F__OP_78__MODE, ITAB__0F__OP_78__MODE__OP_00__VENDOR, ITAB__0F__OP_78__MODE__OP_01__VENDOR, ITAB__0F__OP_78__MODE__OP_02__VENDOR, ITAB__0F__OP_79__MODE, ITAB__0F__OP_79__MODE__OP_00__VENDOR, ITAB__0F__OP_79__MODE__OP_01__VENDOR, ITAB__0F__OP_79__MODE__OP_02__VENDOR, ITAB__0F__OP_A6__MOD, ITAB__0F__OP_A6__MOD__OP_01__RM, ITAB__0F__OP_A6__MOD__OP_01__RM__OP_00__REG, ITAB__0F__OP_A7__MOD, ITAB__0F__OP_A7__MOD__OP_01__RM, ITAB__0F__OP_A7__MOD__OP_01__RM__OP_00__REG, ITAB__0F__OP_AE__REG, ITAB__0F__OP_AE__REG__OP_04__MOD, ITAB__0F__OP_AE__REG__OP_05__MOD, ITAB__0F__OP_AE__REG__OP_05__MOD__OP_01__RM, ITAB__0F__OP_AE__REG__OP_06__MOD, ITAB__0F__OP_AE__REG__OP_06__MOD__OP_01__RM, ITAB__0F__OP_AE__REG__OP_07__MOD, ITAB__0F__OP_AE__REG__OP_07__MOD__OP_01__RM, ITAB__0F__OP_BA__REG, ITAB__0F__OP_C7__REG, ITAB__0F__OP_C7__REG__OP_06__VENDOR, ITAB__0F__OP_C7__REG__OP_07__VENDOR, ITAB__0F__OP_D9__MOD, ITAB__0F__OP_D9__MOD__OP_01__X87, ITAB__1BYTE, ITAB__1BYTE__OP_60__OSIZE, ITAB__1BYTE__OP_61__OSIZE, ITAB__1BYTE__OP_63__MODE, ITAB__1BYTE__OP_6D__OSIZE, ITAB__1BYTE__OP_6F__OSIZE, ITAB__1BYTE__OP_80__REG, ITAB__1BYTE__OP_81__REG, ITAB__1BYTE__OP_82__REG, ITAB__1BYTE__OP_83__REG, ITAB__1BYTE__OP_8F__REG, ITAB__1BYTE__OP_98__OSIZE, ITAB__1BYTE__OP_99__OSIZE, ITAB__1BYTE__OP_9C__MODE, ITAB__1BYTE__OP_9C__MODE__OP_00__OSIZE, ITAB__1BYTE__OP_9C__MODE__OP_01__OSIZE, ITAB__1BYTE__OP_9C__MODE__OP_02__OSIZE, ITAB__1BYTE__OP_9D__MODE, ITAB__1BYTE__OP_9D__MODE__OP_00__OSIZE, ITAB__1BYTE__OP_9D__MODE__OP_01__OSIZE, ITAB__1BYTE__OP_A5__OSIZE, ITAB__1BYTE__OP_A7__OSIZE, ITAB__1BYTE__OP_AB__OSIZE, ITAB__1BYTE__OP_AD__OSIZE, ITAB__1BYTE__OP_AF__OSIZE, ITAB__1BYTE__OP_C0__REG, ITAB__1BYTE__OP_C1__REG, ITAB__1BYTE__OP_C6__REG, ITAB__1BYTE__OP_C7__REG, ITAB__1BYTE__OP_CF__OSIZE, ITAB__1BYTE__OP_D0__REG, ITAB__1BYTE__OP_D1__REG, ITAB__1BYTE__OP_D2__REG, ITAB__1BYTE__OP_D3__REG, ITAB__1BYTE__OP_D8__MOD, ITAB__1BYTE__OP_D8__MOD__OP_00__REG, ITAB__1BYTE__OP_D8__MOD__OP_01__X87, ITAB__1BYTE__OP_D9__MOD, ITAB__1BYTE__OP_D9__MOD__OP_00__REG, ITAB__1BYTE__OP_D9__MOD__OP_01__X87, ITAB__1BYTE__OP_DA__MOD, ITAB__1BYTE__OP_DA__MOD__OP_00__REG, ITAB__1BYTE__OP_DA__MOD__OP_01__X87, ITAB__1BYTE__OP_DB__MOD, ITAB__1BYTE__OP_DB__MOD__OP_00__REG, ITAB__1BYTE__OP_DB__MOD__OP_01__X87, ITAB__1BYTE__OP_DC__MOD, ITAB__1BYTE__OP_DC__MOD__OP_00__REG, ITAB__1BYTE__OP_DC__MOD__OP_01__X87, ITAB__1BYTE__OP_DD__MOD, ITAB__1BYTE__OP_DD__MOD__OP_00__REG, ITAB__1BYTE__OP_DD__MOD__OP_01__X87, ITAB__1BYTE__OP_DE__MOD, ITAB__1BYTE__OP_DE__MOD__OP_00__REG, ITAB__1BYTE__OP_DE__MOD__OP_01__X87, ITAB__1BYTE__OP_DF__MOD, ITAB__1BYTE__OP_DF__MOD__OP_00__REG, ITAB__1BYTE__OP_DF__MOD__OP_01__X87, ITAB__1BYTE__OP_E3__ASIZE, ITAB__1BYTE__OP_F6__REG, ITAB__1BYTE__OP_F7__REG, ITAB__1BYTE__OP_FE__REG, ITAB__1BYTE__OP_FF__REG, ITAB__3DNOW, ITAB__PFX_SSE66__0F, ITAB__PFX_SSE66__0F__38, ITAB__PFX_SSE66__0F__38__OP_80__MODE, ITAB__PFX_SSE66__0F__38__OP_80__MODE__OP_01__VENDOR, ITAB__PFX_SSE66__0F__38__OP_80__MODE__OP_02__VENDOR, ITAB__PFX_SSE66__0F__38__OP_81__MODE, ITAB__PFX_SSE66__0F__38__OP_81__MODE__OP_01__VENDOR, ITAB__PFX_SSE66__0F__38__OP_81__MODE__OP_02__VENDOR, ITAB__PFX_SSE66__0F__OP_71__REG, ITAB__PFX_SSE66__0F__OP_72__REG, ITAB__PFX_SSE66__0F__OP_73__REG, ITAB__PFX_SSE66__0F__OP_C7__REG, ITAB__PFX_SSE66__0F__OP_C7__REG__OP_06__VENDOR, ITAB__PFX_SSEF2__0F, ITAB__PFX_SSEF3__0F, ITAB__PFX_SSEF3__0F__OP_C7__REG, ITAB__PFX_SSEF3__0F__OP_C7__REG__OP_06__VENDOR, }; enum ud_mnemonic_code { UD_I3dnow, UD_Iaaa, UD_Iaad, UD_Iaam, UD_Iaas, UD_Iadc, UD_Iadd, UD_Iaddpd, UD_Iaddps, UD_Iaddsd, UD_Iaddss, UD_Iaddsubpd, UD_Iaddsubps, UD_Iand, UD_Iandpd, UD_Iandps, UD_Iandnpd, UD_Iandnps, UD_Iarpl, UD_Imovsxd, UD_Ibound, UD_Ibsf, UD_Ibsr, UD_Ibswap, UD_Ibt, UD_Ibtc, UD_Ibtr, UD_Ibts, UD_Icall, UD_Icbw, UD_Icwde, UD_Icdqe, UD_Iclc, UD_Icld, UD_Iclflush, UD_Iclgi, UD_Icli, UD_Iclts, UD_Icmc, UD_Icmovo, UD_Icmovno, UD_Icmovb, UD_Icmovae, UD_Icmovz, UD_Icmovnz, UD_Icmovbe, UD_Icmova, UD_Icmovs, UD_Icmovns, UD_Icmovp, UD_Icmovnp, UD_Icmovl, UD_Icmovge, UD_Icmovle, UD_Icmovg, UD_Icmp, UD_Icmppd, UD_Icmpps, UD_Icmpsb, UD_Icmpsw, UD_Icmpsd, UD_Icmpsq, UD_Icmpss, UD_Icmpxchg, UD_Icmpxchg8b, UD_Icomisd, UD_Icomiss, UD_Icpuid, UD_Icvtdq2pd, UD_Icvtdq2ps, UD_Icvtpd2dq, UD_Icvtpd2pi, UD_Icvtpd2ps, UD_Icvtpi2ps, UD_Icvtpi2pd, UD_Icvtps2dq, UD_Icvtps2pi, UD_Icvtps2pd, UD_Icvtsd2si, UD_Icvtsd2ss, UD_Icvtsi2ss, UD_Icvtss2si, UD_Icvtss2sd, UD_Icvttpd2pi, UD_Icvttpd2dq, UD_Icvttps2dq, UD_Icvttps2pi, UD_Icvttsd2si, UD_Icvtsi2sd, UD_Icvttss2si, UD_Icwd, UD_Icdq, UD_Icqo, UD_Idaa, UD_Idas, UD_Idec, UD_Idiv, UD_Idivpd, UD_Idivps, UD_Idivsd, UD_Idivss, UD_Iemms, UD_Ienter, UD_If2xm1, UD_Ifabs, UD_Ifadd, UD_Ifaddp, UD_Ifbld, UD_Ifbstp, UD_Ifchs, UD_Ifclex, UD_Ifcmovb, UD_Ifcmove, UD_Ifcmovbe, UD_Ifcmovu, UD_Ifcmovnb, UD_Ifcmovne, UD_Ifcmovnbe, UD_Ifcmovnu, UD_Ifucomi, UD_Ifcom, UD_Ifcom2, UD_Ifcomp3, UD_Ifcomi, UD_Ifucomip, UD_Ifcomip, UD_Ifcomp, UD_Ifcomp5, UD_Ifcompp, UD_Ifcos, UD_Ifdecstp, UD_Ifdiv, UD_Ifdivp, UD_Ifdivr, UD_Ifdivrp, UD_Ifemms, UD_Iffree, UD_Iffreep, UD_Ificom, UD_Ificomp, UD_Ifild, UD_Ifncstp, UD_Ifninit, UD_Ifiadd, UD_Ifidivr, UD_Ifidiv, UD_Ifisub, UD_Ifisubr, UD_Ifist, UD_Ifistp, UD_Ifisttp, UD_Ifld, UD_Ifld1, UD_Ifldl2t, UD_Ifldl2e, UD_Ifldlpi, UD_Ifldlg2, UD_Ifldln2, UD_Ifldz, UD_Ifldcw, UD_Ifldenv, UD_Ifmul, UD_Ifmulp, UD_Ifimul, UD_Ifnop, UD_Ifpatan, UD_Ifprem, UD_Ifprem1, UD_Ifptan, UD_Ifrndint, UD_Ifrstor, UD_Ifnsave, UD_Ifscale, UD_Ifsin, UD_Ifsincos, UD_Ifsqrt, UD_Ifstp, UD_Ifstp1, UD_Ifstp8, UD_Ifstp9, UD_Ifst, UD_Ifnstcw, UD_Ifnstenv, UD_Ifnstsw, UD_Ifsub, UD_Ifsubp, UD_Ifsubr, UD_Ifsubrp, UD_Iftst, UD_Ifucom, UD_Ifucomp, UD_Ifucompp, UD_Ifxam, UD_Ifxch, UD_Ifxch4, UD_Ifxch7, UD_Ifxrstor, UD_Ifxsave, UD_Ifpxtract, UD_Ifyl2x, UD_Ifyl2xp1, UD_Ihaddpd, UD_Ihaddps, UD_Ihlt, UD_Ihsubpd, UD_Ihsubps, UD_Iidiv, UD_Iin, UD_Iimul, UD_Iinc, UD_Iinsb, UD_Iinsw, UD_Iinsd, UD_Iint1, UD_Iint3, UD_Iint, UD_Iinto, UD_Iinvd, UD_Iinvept, UD_Iinvlpg, UD_Iinvlpga, UD_Iinvvpid, UD_Iiretw, UD_Iiretd, UD_Iiretq, UD_Ijo, UD_Ijno, UD_Ijb, UD_Ijae, UD_Ijz, UD_Ijnz, UD_Ijbe, UD_Ija, UD_Ijs, UD_Ijns, UD_Ijp, UD_Ijnp, UD_Ijl, UD_Ijge, UD_Ijle, UD_Ijg, UD_Ijcxz, UD_Ijecxz, UD_Ijrcxz, UD_Ijmp, UD_Ilahf, UD_Ilar, UD_Ilddqu, UD_Ildmxcsr, UD_Ilds, UD_Ilea, UD_Iles, UD_Ilfs, UD_Ilgs, UD_Ilidt, UD_Ilss, UD_Ileave, UD_Ilfence, UD_Ilgdt, UD_Illdt, UD_Ilmsw, UD_Ilock, UD_Ilodsb, UD_Ilodsw, UD_Ilodsd, UD_Ilodsq, UD_Iloopnz, UD_Iloope, UD_Iloop, UD_Ilsl, UD_Iltr, UD_Imaskmovq, UD_Imaxpd, UD_Imaxps, UD_Imaxsd, UD_Imaxss, UD_Imfence, UD_Iminpd, UD_Iminps, UD_Iminsd, UD_Iminss, UD_Imonitor, UD_Imontmul, UD_Imov, UD_Imovapd, UD_Imovaps, UD_Imovd, UD_Imovddup, UD_Imovdqa, UD_Imovdqu, UD_Imovdq2q, UD_Imovhpd, UD_Imovhps, UD_Imovlhps, UD_Imovlpd, UD_Imovlps, UD_Imovhlps, UD_Imovmskpd, UD_Imovmskps, UD_Imovntdq, UD_Imovnti, UD_Imovntpd, UD_Imovntps, UD_Imovntq, UD_Imovq, UD_Imovqa, UD_Imovq2dq, UD_Imovsb, UD_Imovsw, UD_Imovsd, UD_Imovsq, UD_Imovsldup, UD_Imovshdup, UD_Imovss, UD_Imovsx, UD_Imovupd, UD_Imovups, UD_Imovzx, UD_Imul, UD_Imulpd, UD_Imulps, UD_Imulsd, UD_Imulss, UD_Imwait, UD_Ineg, UD_Inop, UD_Inot, UD_Ior, UD_Iorpd, UD_Iorps, UD_Iout, UD_Ioutsb, UD_Ioutsw, UD_Ioutsd, UD_Ioutsq, UD_Ipacksswb, UD_Ipackssdw, UD_Ipackuswb, UD_Ipaddb, UD_Ipaddw, UD_Ipaddq, UD_Ipaddsb, UD_Ipaddsw, UD_Ipaddusb, UD_Ipaddusw, UD_Ipand, UD_Ipandn, UD_Ipause, UD_Ipavgb, UD_Ipavgw, UD_Ipcmpeqb, UD_Ipcmpeqw, UD_Ipcmpeqd, UD_Ipcmpgtb, UD_Ipcmpgtw, UD_Ipcmpgtd, UD_Ipextrw, UD_Ipinsrw, UD_Ipmaddwd, UD_Ipmaxsw, UD_Ipmaxub, UD_Ipminsw, UD_Ipminub, UD_Ipmovmskb, UD_Ipmulhuw, UD_Ipmulhw, UD_Ipmullw, UD_Ipmuludq, UD_Ipop, UD_Ipopa, UD_Ipopad, UD_Ipopfw, UD_Ipopfd, UD_Ipopfq, UD_Ipor, UD_Iprefetch, UD_Iprefetchnta, UD_Iprefetcht0, UD_Iprefetcht1, UD_Iprefetcht2, UD_Ipsadbw, UD_Ipshufd, UD_Ipshufhw, UD_Ipshuflw, UD_Ipshufw, UD_Ipslldq, UD_Ipsllw, UD_Ipslld, UD_Ipsllq, UD_Ipsraw, UD_Ipsrad, UD_Ipsrlw, UD_Ipsrld, UD_Ipsrlq, UD_Ipsrldq, UD_Ipsubb, UD_Ipsubw, UD_Ipsubd, UD_Ipsubq, UD_Ipsubsb, UD_Ipsubsw, UD_Ipsubusb, UD_Ipsubusw, UD_Ipunpckhbw, UD_Ipunpckhwd, UD_Ipunpckhdq, UD_Ipunpckhqdq, UD_Ipunpcklbw, UD_Ipunpcklwd, UD_Ipunpckldq, UD_Ipunpcklqdq, UD_Ipi2fw, UD_Ipi2fd, UD_Ipf2iw, UD_Ipf2id, UD_Ipfnacc, UD_Ipfpnacc, UD_Ipfcmpge, UD_Ipfmin, UD_Ipfrcp, UD_Ipfrsqrt, UD_Ipfsub, UD_Ipfadd, UD_Ipfcmpgt, UD_Ipfmax, UD_Ipfrcpit1, UD_Ipfrspit1, UD_Ipfsubr, UD_Ipfacc, UD_Ipfcmpeq, UD_Ipfmul, UD_Ipfrcpit2, UD_Ipmulhrw, UD_Ipswapd, UD_Ipavgusb, UD_Ipush, UD_Ipusha, UD_Ipushad, UD_Ipushfw, UD_Ipushfd, UD_Ipushfq, UD_Ipxor, UD_Ircl, UD_Ircr, UD_Irol, UD_Iror, UD_Ircpps, UD_Ircpss, UD_Irdmsr, UD_Irdpmc, UD_Irdtsc, UD_Irdtscp, UD_Irepne, UD_Irep, UD_Iret, UD_Iretf, UD_Irsm, UD_Irsqrtps, UD_Irsqrtss, UD_Isahf, UD_Isal, UD_Isalc, UD_Isar, UD_Ishl, UD_Ishr, UD_Isbb, UD_Iscasb, UD_Iscasw, UD_Iscasd, UD_Iscasq, UD_Iseto, UD_Isetno, UD_Isetb, UD_Isetnb, UD_Isetz, UD_Isetnz, UD_Isetbe, UD_Iseta, UD_Isets, UD_Isetns, UD_Isetp, UD_Isetnp, UD_Isetl, UD_Isetge, UD_Isetle, UD_Isetg, UD_Isfence, UD_Isgdt, UD_Ishld, UD_Ishrd, UD_Ishufpd, UD_Ishufps, UD_Isidt, UD_Isldt, UD_Ismsw, UD_Isqrtps, UD_Isqrtpd, UD_Isqrtsd, UD_Isqrtss, UD_Istc, UD_Istd, UD_Istgi, UD_Isti, UD_Iskinit, UD_Istmxcsr, UD_Istosb, UD_Istosw, UD_Istosd, UD_Istosq, UD_Istr, UD_Isub, UD_Isubpd, UD_Isubps, UD_Isubsd, UD_Isubss, UD_Iswapgs, UD_Isyscall, UD_Isysenter, UD_Isysexit, UD_Isysret, UD_Itest, UD_Iucomisd, UD_Iucomiss, UD_Iud2, UD_Iunpckhpd, UD_Iunpckhps, UD_Iunpcklps, UD_Iunpcklpd, UD_Iverr, UD_Iverw, UD_Ivmcall, UD_Ivmclear, UD_Ivmxon, UD_Ivmptrld, UD_Ivmptrst, UD_Ivmlaunch, UD_Ivmresume, UD_Ivmxoff, UD_Ivmread, UD_Ivmwrite, UD_Ivmrun, UD_Ivmmcall, UD_Ivmload, UD_Ivmsave, UD_Iwait, UD_Iwbinvd, UD_Iwrmsr, UD_Ixadd, UD_Ixchg, UD_Ixlatb, UD_Ixor, UD_Ixorpd, UD_Ixorps, UD_Ixcryptecb, UD_Ixcryptcbc, UD_Ixcryptctr, UD_Ixcryptcfb, UD_Ixcryptofb, UD_Ixgetbv, UD_Ixrstor, UD_Ixsetbv, UD_Ixsave, UD_Ixsha1, UD_Ixsha256, UD_Ixstore, UD_Idb, UD_Iinvalid, UD_Id3vil, UD_Ina, UD_Igrp_reg, UD_Igrp_rm, UD_Igrp_vendor, UD_Igrp_x87, UD_Igrp_mode, UD_Igrp_osize, UD_Igrp_asize, UD_Igrp_mod, UD_Igrp_3byte, UD_Inone, } UD_ATTR_PACKED; /* itab entry operand definitions */ #define O_AH { OP_AH, SZ_NA } #define O_AHr12b { OP_AHr12b, SZ_NA } #define O_AL { OP_AL, SZ_NA } #define O_ALr8b { OP_ALr8b, SZ_NA } #define O_AX { OP_AX, SZ_NA } #define O_Ap { OP_A, SZ_P } #define O_BH { OP_BH, SZ_NA } #define O_BHr15b { OP_BHr15b, SZ_NA } #define O_BL { OP_BL, SZ_NA } #define O_BLr11b { OP_BLr11b, SZ_NA } #define O_BP { OP_BP, SZ_NA } #define O_BX { OP_BX, SZ_NA } #define O_C { OP_C, SZ_NA } #define O_CH { OP_CH, SZ_NA } #define O_CHr13b { OP_CHr13b, SZ_NA } #define O_CL { OP_CL, SZ_NA } #define O_CLr9b { OP_CLr9b, SZ_NA } #define O_CS { OP_CS, SZ_NA } #define O_CX { OP_CX, SZ_NA } #define O_D { OP_D, SZ_NA } #define O_DH { OP_DH, SZ_NA } #define O_DHr14b { OP_DHr14b, SZ_NA } #define O_DI { OP_DI, SZ_NA } #define O_DL { OP_DL, SZ_NA } #define O_DLr10b { OP_DLr10b, SZ_NA } #define O_DS { OP_DS, SZ_NA } #define O_DX { OP_DX, SZ_NA } #define O_E { OP_E, SZ_NA } #define O_ES { OP_ES, SZ_NA } #define O_Eb { OP_E, SZ_B } #define O_Ed { OP_E, SZ_D } #define O_Ep { OP_E, SZ_P } #define O_Eq { OP_E, SZ_Q } #define O_Ev { OP_E, SZ_V } #define O_Ew { OP_E, SZ_W } #define O_Ex { OP_E, SZ_MDQ } #define O_Ez { OP_E, SZ_Z } #define O_FS { OP_FS, SZ_NA } #define O_G { OP_G, SZ_NA } #define O_GS { OP_GS, SZ_NA } #define O_Gb { OP_G, SZ_B } #define O_Gd { OP_G, SZ_D } #define O_Gq { OP_G, SZ_Q } #define O_Gv { OP_G, SZ_V } #define O_Gvw { OP_G, SZ_MDQ } #define O_Gw { OP_G, SZ_W } #define O_Gx { OP_G, SZ_MDQ } #define O_Gz { OP_G, SZ_Z } #define O_I1 { OP_I1, SZ_NA } #define O_I3 { OP_I3, SZ_NA } #define O_Ib { OP_I, SZ_B } #define O_Isb { OP_I, SZ_SB } #define O_Iv { OP_I, SZ_V } #define O_Iw { OP_I, SZ_W } #define O_Iz { OP_I, SZ_Z } #define O_Jb { OP_J, SZ_B } #define O_Jv { OP_J, SZ_V } #define O_Jz { OP_J, SZ_Z } #define O_M { OP_M, SZ_NA } #define O_Mb { OP_M, SZ_B } #define O_Md { OP_M, SZ_D } #define O_Mo { OP_M, SZ_O } #define O_Mq { OP_M, SZ_Q } #define O_Ms { OP_M, SZ_W } #define O_Mt { OP_M, SZ_T } #define O_Mw { OP_M, SZ_W } #define O_NONE { OP_NONE, SZ_NA } #define O_Ob { OP_O, SZ_B } #define O_Ov { OP_O, SZ_V } #define O_Ow { OP_O, SZ_W } #define O_P { OP_P, SZ_NA } #define O_PR { OP_PR, SZ_NA } #define O_Q { OP_Q, SZ_NA } #define O_R { OP_R, SZ_RDQ } #define O_S { OP_S, SZ_NA } #define O_SI { OP_SI, SZ_NA } #define O_SP { OP_SP, SZ_NA } #define O_SS { OP_SS, SZ_NA } #define O_ST0 { OP_ST0, SZ_NA } #define O_ST1 { OP_ST1, SZ_NA } #define O_ST2 { OP_ST2, SZ_NA } #define O_ST3 { OP_ST3, SZ_NA } #define O_ST4 { OP_ST4, SZ_NA } #define O_ST5 { OP_ST5, SZ_NA } #define O_ST6 { OP_ST6, SZ_NA } #define O_ST7 { OP_ST7, SZ_NA } #define O_V { OP_V, SZ_NA } #define O_VR { OP_VR, SZ_NA } #define O_W { OP_W, SZ_NA } #define O_eAX { OP_eAX, SZ_NA } #define O_eBP { OP_eBP, SZ_NA } #define O_eBX { OP_eBX, SZ_NA } #define O_eCX { OP_eCX, SZ_NA } #define O_eDI { OP_eDI, SZ_NA } #define O_eDX { OP_eDX, SZ_NA } #define O_eSI { OP_eSI, SZ_NA } #define O_eSP { OP_eSP, SZ_NA } #define O_jDP { OP_J, SZ_DP } #define O_jWP { OP_J, SZ_WP } #define O_rAX { OP_rAX, SZ_NA } #define O_rAXr8 { OP_rAXr8, SZ_NA } #define O_rBP { OP_rBP, SZ_NA } #define O_rBPr13 { OP_rBPr13, SZ_NA } #define O_rBX { OP_rBX, SZ_NA } #define O_rBXr11 { OP_rBXr11, SZ_NA } #define O_rCX { OP_rCX, SZ_NA } #define O_rCXr9 { OP_rCXr9, SZ_NA } #define O_rDI { OP_rDI, SZ_NA } #define O_rDIr15 { OP_rDIr15, SZ_NA } #define O_rDX { OP_rDX, SZ_NA } #define O_rDXr10 { OP_rDXr10, SZ_NA } #define O_rSI { OP_rSI, SZ_NA } #define O_rSIr14 { OP_rSIr14, SZ_NA } #define O_rSP { OP_rSP, SZ_NA } #define O_rSPr12 { OP_rSPr12, SZ_NA } extern const char* ud_mnemonics_str[];; extern struct ud_itab_entry* ud_itab_list[]; #endif ksplice-0.9.9/kmodsrc/x86/libudis86/opgen.py0000644000000000000000000005020411225645327017253 0ustar rootroot#!/usr/bin/env python import os import sys import string from xml.dom import minidom # # opgen.py -- generates tables and constants for decoding # # - itab.c # - itab.h # # # special mnemonic types for internal purposes. # spl_mnm_types = [ 'd3vil', \ 'na', \ 'grp_reg', \ 'grp_rm', \ 'grp_vendor', \ 'grp_x87', \ 'grp_mode', \ 'grp_osize', \ 'grp_asize', \ 'grp_mod', \ 'grp_3byte', \ 'none' \ ] # # opcode-vendor dictionary # vend_dict = { 'AMD' : '00', 'INTEL' : '01', 'ANY' : '02' } # # opcode-mode dictionary # mode_dict = { '16' : '00', '32' : '01', '64' : '02' } # # opcode-operand dictionary # operand_dict = { "Ap" : [ "OP_A" , "SZ_P" ], "E" : [ "OP_E" , "SZ_NA" ], "Eb" : [ "OP_E" , "SZ_B" ], "Ew" : [ "OP_E" , "SZ_W" ], "Ev" : [ "OP_E" , "SZ_V" ], "Ed" : [ "OP_E" , "SZ_D" ], "Eq" : [ "OP_E" , "SZ_Q" ], "Ez" : [ "OP_E" , "SZ_Z" ], "Ex" : [ "OP_E" , "SZ_MDQ" ], "Ep" : [ "OP_E" , "SZ_P" ], "G" : [ "OP_G" , "SZ_NA" ], "Gb" : [ "OP_G" , "SZ_B" ], "Gw" : [ "OP_G" , "SZ_W" ], "Gv" : [ "OP_G" , "SZ_V" ], "Gvw" : [ "OP_G" , "SZ_MDQ" ], "Gd" : [ "OP_G" , "SZ_D" ], "Gq" : [ "OP_G" , "SZ_Q" ], "Gx" : [ "OP_G" , "SZ_MDQ" ], "Gz" : [ "OP_G" , "SZ_Z" ], "M" : [ "OP_M" , "SZ_NA" ], "Mb" : [ "OP_M" , "SZ_B" ], "Mw" : [ "OP_M" , "SZ_W" ], "Ms" : [ "OP_M" , "SZ_W" ], "Md" : [ "OP_M" , "SZ_D" ], "Mq" : [ "OP_M" , "SZ_Q" ], "Mt" : [ "OP_M" , "SZ_T" ], "Mo" : [ "OP_M" , "SZ_O" ], "I1" : [ "OP_I1" , "SZ_NA" ], "I3" : [ "OP_I3" , "SZ_NA" ], "Ib" : [ "OP_I" , "SZ_B" ], "Isb" : [ "OP_I" , "SZ_SB" ], "Iw" : [ "OP_I" , "SZ_W" ], "Iv" : [ "OP_I" , "SZ_V" ], "Iz" : [ "OP_I" , "SZ_Z" ], "Jv" : [ "OP_J" , "SZ_V" ], "Jz" : [ "OP_J" , "SZ_Z" ], "Jb" : [ "OP_J" , "SZ_B" ], "R" : [ "OP_R" , "SZ_RDQ" ], "C" : [ "OP_C" , "SZ_NA" ], "D" : [ "OP_D" , "SZ_NA" ], "S" : [ "OP_S" , "SZ_NA" ], "Ob" : [ "OP_O" , "SZ_B" ], "Ow" : [ "OP_O" , "SZ_W" ], "Ov" : [ "OP_O" , "SZ_V" ], "V" : [ "OP_V" , "SZ_NA" ], "W" : [ "OP_W" , "SZ_NA" ], "P" : [ "OP_P" , "SZ_NA" ], "Q" : [ "OP_Q" , "SZ_NA" ], "VR" : [ "OP_VR" , "SZ_NA" ], "PR" : [ "OP_PR" , "SZ_NA" ], "AL" : [ "OP_AL" , "SZ_NA" ], "CL" : [ "OP_CL" , "SZ_NA" ], "DL" : [ "OP_DL" , "SZ_NA" ], "BL" : [ "OP_BL" , "SZ_NA" ], "AH" : [ "OP_AH" , "SZ_NA" ], "CH" : [ "OP_CH" , "SZ_NA" ], "DH" : [ "OP_DH" , "SZ_NA" ], "BH" : [ "OP_BH" , "SZ_NA" ], "AX" : [ "OP_AX" , "SZ_NA" ], "CX" : [ "OP_CX" , "SZ_NA" ], "DX" : [ "OP_DX" , "SZ_NA" ], "BX" : [ "OP_BX" , "SZ_NA" ], "SI" : [ "OP_SI" , "SZ_NA" ], "DI" : [ "OP_DI" , "SZ_NA" ], "SP" : [ "OP_SP" , "SZ_NA" ], "BP" : [ "OP_BP" , "SZ_NA" ], "eAX" : [ "OP_eAX" , "SZ_NA" ], "eCX" : [ "OP_eCX" , "SZ_NA" ], "eDX" : [ "OP_eDX" , "SZ_NA" ], "eBX" : [ "OP_eBX" , "SZ_NA" ], "eSI" : [ "OP_eSI" , "SZ_NA" ], "eDI" : [ "OP_eDI" , "SZ_NA" ], "eSP" : [ "OP_eSP" , "SZ_NA" ], "eBP" : [ "OP_eBP" , "SZ_NA" ], "rAX" : [ "OP_rAX" , "SZ_NA" ], "rCX" : [ "OP_rCX" , "SZ_NA" ], "rBX" : [ "OP_rBX" , "SZ_NA" ], "rDX" : [ "OP_rDX" , "SZ_NA" ], "rSI" : [ "OP_rSI" , "SZ_NA" ], "rDI" : [ "OP_rDI" , "SZ_NA" ], "rSP" : [ "OP_rSP" , "SZ_NA" ], "rBP" : [ "OP_rBP" , "SZ_NA" ], "ES" : [ "OP_ES" , "SZ_NA" ], "CS" : [ "OP_CS" , "SZ_NA" ], "DS" : [ "OP_DS" , "SZ_NA" ], "SS" : [ "OP_SS" , "SZ_NA" ], "GS" : [ "OP_GS" , "SZ_NA" ], "FS" : [ "OP_FS" , "SZ_NA" ], "ST0" : [ "OP_ST0" , "SZ_NA" ], "ST1" : [ "OP_ST1" , "SZ_NA" ], "ST2" : [ "OP_ST2" , "SZ_NA" ], "ST3" : [ "OP_ST3" , "SZ_NA" ], "ST4" : [ "OP_ST4" , "SZ_NA" ], "ST5" : [ "OP_ST5" , "SZ_NA" ], "ST6" : [ "OP_ST6" , "SZ_NA" ], "ST7" : [ "OP_ST7" , "SZ_NA" ], "NONE" : [ "OP_NONE" , "SZ_NA" ], "ALr8b" : [ "OP_ALr8b" , "SZ_NA" ], "CLr9b" : [ "OP_CLr9b" , "SZ_NA" ], "DLr10b" : [ "OP_DLr10b" , "SZ_NA" ], "BLr11b" : [ "OP_BLr11b" , "SZ_NA" ], "AHr12b" : [ "OP_AHr12b" , "SZ_NA" ], "CHr13b" : [ "OP_CHr13b" , "SZ_NA" ], "DHr14b" : [ "OP_DHr14b" , "SZ_NA" ], "BHr15b" : [ "OP_BHr15b" , "SZ_NA" ], "rAXr8" : [ "OP_rAXr8" , "SZ_NA" ], "rCXr9" : [ "OP_rCXr9" , "SZ_NA" ], "rDXr10" : [ "OP_rDXr10" , "SZ_NA" ], "rBXr11" : [ "OP_rBXr11" , "SZ_NA" ], "rSPr12" : [ "OP_rSPr12" , "SZ_NA" ], "rBPr13" : [ "OP_rBPr13" , "SZ_NA" ], "rSIr14" : [ "OP_rSIr14" , "SZ_NA" ], "rDIr15" : [ "OP_rDIr15" , "SZ_NA" ], "jWP" : [ "OP_J" , "SZ_WP" ], "jDP" : [ "OP_J" , "SZ_DP" ], } # # opcode prefix dictionary # pfx_dict = { "aso" : "P_aso", "oso" : "P_oso", "rexw" : "P_rexw", "rexb" : "P_rexb", "rexx" : "P_rexx", "rexr" : "P_rexr", "inv64" : "P_inv64", "def64" : "P_def64", "depM" : "P_depM", "cast1" : "P_c1", "cast2" : "P_c2", "cast3" : "P_c3" } # # globals # opr_constants = [] siz_constants = [] tables = {} table_sizes = {} mnm_list = [] default_opr = 'O_NONE, O_NONE, O_NONE' # # collect the operand/size constants # for o in operand_dict.keys(): if not (operand_dict[o][0] in opr_constants): opr_constants.append(operand_dict[o][0]) if not (operand_dict[o][1] in siz_constants): siz_constants.append(operand_dict[o][1]) xmlDoc = minidom.parse(sys.argv[1]) tlNode = xmlDoc.firstChild # # look for top-level optable node # while tlNode and tlNode.localName != "x86optable": tlNode = tlNode.nextSibling # # creates a table entry # def centry(i, defmap): if defmap["type"][0:3] == "grp": opr = default_opr mnm = 'UD_I' + defmap["type"].lower() pfx = defmap["name"].upper() elif defmap["type"] == "leaf": mnm = "UD_I" + defmap["name"] opr = defmap["opr"] pfx = defmap["pfx"] if len(mnm) == 0: mnm = "UD_Ina" if len(opr) == 0: opr = default_opr if len(pfx) == 0: pfx = "P_none" else: opr = default_opr pfx = "P_none" mnm = "UD_Iinvalid" return " /* %s */ { %-16s %-26s %s },\n" % (i, mnm + ',', opr + ',', pfx) # # makes a new table and adds it to the global # list of tables # def mktab(name, size): if not (name in tables.keys()): tables[name] = {} table_sizes[name] = size for node in tlNode.childNodes: opcodes = [] iclass = '' vendor = '' # we are only interested in if node.localName != 'instruction': continue # we need the mnemonic attribute if not ('mnemonic' in node.attributes.keys()): print "error: no mnemonic given in ." sys.exit(-1) # check if this instruction was already defined. # else add it to the global list of mnemonics mnemonic = node.attributes['mnemonic'].value if mnemonic in mnm_list: print "error: multiple declarations of mnemonic='%s'" % mnemonic; sys.exit(-1) else: mnm_list.append(mnemonic) # # collect instruction # - vendor # - class # for n in node.childNodes: if n.localName == 'vendor': vendor = (n.firstChild.data).strip(); elif n.localName == 'class': iclass = n.firstChild.data; # # for each opcode definition # for n in node.childNodes: if n.localName != 'opcode': continue; opcode = n.firstChild.data.strip(); parts = opcode.split(";"); flags = [] opr = [] pfx = [] opr = [] pfx_c = [] # get cast attribute, if given if 'cast' in n.attributes.keys(): pfx_c.append( "P_c" + n.attributes['cast'].value ) # get implicit addressing attribute, if given if 'imp_addr' in n.attributes.keys(): if int( n.attributes['imp_addr'].value ): pfx_c.append( "P_ImpAddr" ) # get mode attribute, if given if 'mode' in n.attributes.keys(): v = (n.attributes['mode'].value).strip() modef = v.split(); for m in modef: if not (m in pfx_dict): print "warning: unrecognized mode attribute '%s'" % m else: pfx_c.append(pfx_dict[m]) # # split opcode definition into # 1. prefixes (pfx) # 2. opcode bytes (opc) # 3. operands # if len(parts) == 1: opc = parts[0].split() elif len(parts) == 2: opc = parts[0].split() opr = parts[1].split() for o in opc: if o in pfx_dict: pfx = parts[0].split() opc = parts[1].split() break elif len(parts) == 3: pfx = parts[0].split() opc = parts[1].split() opr = parts[2].split() else: print "error: invalid opcode definition of %s\n" % mnemonic sys.exit(-1) # Convert opcodes to upper case for i in range(len(opc)): opc[i] = opc[i].upper() # # check for special cases of instruction translation # and ignore them # if mnemonic == 'pause' or \ ( mnemonic == 'nop' and opc[0] == '90' ) or \ mnemonic == 'invalid' or \ mnemonic == 'db' : continue # # Convert prefix # for p in pfx: if not ( p in pfx_dict.keys() ): print "error: invalid prefix specification: %s \n" % pfx pfx_c.append( pfx_dict[p] ) if len(pfx) == 0: pfx_c.append( "P_none" ) pfx = "|".join( pfx_c ) # # Convert operands # opr_c = [ "O_NONE", "O_NONE", "O_NONE" ] for i in range(len(opr)): if not (opr[i] in operand_dict.keys()): print "error: invalid operand declaration: %s\n" % opr[i] opr_c[i] = "O_" + opr[i] opr = "%-8s %-8s %s" % (opr_c[0] + ",", opr_c[1] + ",", opr_c[2]) table_sse = '' table_name = 'itab__1byte' table_size = 256 table_index = '' for op in opc: if op[0:3] == 'SSE': table_sse = op elif op == '0F' and len(table_sse): table_name = "itab__pfx_%s__0f" % table_sse table_size = 256 table_sse = '' elif op == '0F': table_name = "itab__0f" table_size = 256 elif op == '38' and (table_name == "itab__0f" or table_name == "itab__pfx_SSE66__0f"): table_index = '38' tables[table_name][table_index] = { \ 'type' : 'grp_3byte', \ 'name' : "%s__38" % (table_name) \ } table_name = tables[table_name][table_index]['name'] table_size = 256 elif op[0:5] == '/X87=': tables[table_name][table_index] = { \ 'type' : 'grp_x87', \ 'name' : "%s__op_%s__x87" % (table_name, table_index) \ } table_name = tables[table_name][table_index]['name'] table_index = "%02X" % int(op[5:7], 16) table_size = 64 elif op[0:4] == '/RM=': tables[table_name][table_index] = { \ 'type' : 'grp_rm', \ 'name' : "%s__op_%s__rm" % (table_name, table_index) \ } table_name = tables[table_name][table_index]['name'] table_index = "%02X" % int(op[4:6]) table_size = 8 elif op[0:5] == '/MOD=': tables[table_name][table_index] = { \ 'type' : 'grp_mod', \ 'name' : "%s__op_%s__mod" % (table_name, table_index) \ } table_name = tables[table_name][table_index]['name'] if len(op) == 8: v = op[5:8] else: v = op[5:7] mod_dict = { '!11' : 0, '11' : 1 } table_index = "%02X" % int(mod_dict[v]) table_size = 2 elif op[0:2] == '/O': tables[table_name][table_index] = { \ 'type' : 'grp_osize', \ 'name' : "%s__op_%s__osize" % (table_name, table_index) \ } table_name = tables[table_name][table_index]['name'] table_index = "%02X" % int(mode_dict[op[2:4]]) table_size = 3 elif op[0:2] == '/A': tables[table_name][table_index] = { \ 'type' : 'grp_asize', \ 'name' : "%s__op_%s__asize" % (table_name, table_index) \ } table_name = tables[table_name][table_index]['name'] table_index = "%02X" % int(mode_dict[op[2:4]]) table_size = 3 elif op[0:2] == '/M': tables[table_name][table_index] = { \ 'type' : 'grp_mode', \ 'name' : "%s__op_%s__mode" % (table_name, table_index) \ } table_name = tables[table_name][table_index]['name'] table_index = "%02X" % int(mode_dict[op[2:4]]) table_size = 3 elif op[0:6] == '/3DNOW': table_name = "itab__3dnow" table_size = 256 elif op[0:1] == '/': tables[table_name][table_index] = { \ 'type' : 'grp_reg', \ 'name' : "%s__op_%s__reg" % (table_name, table_index) \ } table_name = tables[table_name][table_index]['name'] table_index = "%02X" % int(op[1:2]) table_size = 8 else: table_index = op mktab(table_name, table_size) if len(vendor): tables[table_name][table_index] = { \ 'type' : 'grp_vendor', \ 'name' : "%s__op_%s__vendor" % (table_name, table_index) \ } table_name = tables[table_name][table_index]['name'] table_index = vend_dict[vendor] table_size = 3 mktab(table_name, table_size) tables[table_name][table_index] = { \ 'type' : 'leaf', \ 'name' : mnemonic, \ 'pfx' : pfx, \ 'opr' : opr, \ 'flags' : flags \ } if len(vendor): tables[table_name][vend_dict['ANY']] = { \ 'type' : 'leaf', \ 'name' : mnemonic, \ 'pfx' : pfx, \ 'opr' : opr, \ 'flags' : flags \ } # --------------------------------------------------------------------- # Generate itab.h # --------------------------------------------------------------------- f = open("itab.h", "w") f.write(''' /* itab.h -- auto generated by opgen.py, do not edit. */ #ifndef UD_ITAB_H #define UD_ITAB_H ''') # # Generate enumeration of size constants # siz_constants.sort() f.write(''' ''') f.write("\nenum ud_itab_vendor_index {\n" ) f.write(" ITAB__VENDOR_INDX__AMD,\n" ) f.write(" ITAB__VENDOR_INDX__INTEL,\n" ) f.write(" ITAB__VENDOR_INDX__ANY,\n" ) f.write("};\n\n") f.write("\nenum ud_itab_mode_index {\n" ) f.write(" ITAB__MODE_INDX__16,\n" ) f.write(" ITAB__MODE_INDX__32,\n" ) f.write(" ITAB__MODE_INDX__64\n" ) f.write("};\n\n") f.write("\nenum ud_itab_mod_index {\n" ) f.write(" ITAB__MOD_INDX__NOT_11,\n" ) f.write(" ITAB__MOD_INDX__11\n" ) f.write("};\n\n") # # Generate enumeration of the tables # table_names = tables.keys() table_names.sort(); f.write( "\nenum ud_itab_index {\n" ) for name in table_names: f.write(" %s,\n" % name.upper() ); f.write( "};\n\n" ) # # Generate mnemonics list # f.write("\nenum ud_mnemonic_code {\n") for m in mnm_list: f.write(" UD_I%s,\n" % m) for m in spl_mnm_types: f.write(" UD_I%s,\n" % m) f.write("} UD_ATTR_PACKED;\n\n") # # Generate operand definitions # f.write("\n/* itab entry operand definitions */\n\n"); operands = operand_dict.keys() operands.sort() for o in operands: f.write("#define O_%-7s { %-12s %-8s }\n" % (o, operand_dict[o][0] + ",", operand_dict[o][1])); f.write("\n"); # # Generate struct defs # f.write( \ ''' extern const char* ud_mnemonics_str[];; extern struct ud_itab_entry* ud_itab_list[]; ''' ) f.write("#endif\n") f.close() # --------------------------------------------------------------------- # Generate itab.c # --------------------------------------------------------------------- f = open("itab.c", "w") f.write(''' /* itab.c -- auto generated by opgen.py, do not edit. */ #include "types.h" #include "decode.h" #include "itab.h" ''') # # generate mnemonic list # f.write("const char * ud_mnemonics_str[] = {\n") for m in mnm_list: f.write(" \"%s\",\n" % m ) f.write("};\n\n") # # generate instruction tables # f.write("\n") for t in table_names: f.write("\nstatic struct ud_itab_entry " + t.lower() + "[%d] = {\n" % table_sizes[t]); for i in range(int(table_sizes[t])): index = "%02X" % i if index in tables[t]: f.write(centry(index, tables[t][index])) else: f.write(centry(index,{"type":"invalid"})) f.write("};\n"); # # write the instruction table list # f.write( "\n/* the order of this table matches enum ud_itab_index */") f.write( "\nstruct ud_itab_entry * ud_itab_list[] = {\n" ) for name in table_names: f.write( " %s,\n" % name.lower() ) f.write( "};\n" ); f.close(); # vim:expandtab # vim:sw=4 # vim:ts=4 ksplice-0.9.9/kmodsrc/x86/ksplice-arch.c0000644000000000000000000005732111244274432016474 0ustar rootroot/* Copyright (C) 2007-2009 Ksplice, Inc. * Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA * 02110-1301, USA. */ #if defined(_ASM_X86_PROCESSOR_H) || \ defined(__ASM_X86_PROCESSOR_H) /* New unified x86 */ #define KSPLICE_IP(x) ((x)->thread.ip) #define KSPLICE_SP(x) ((x)->thread.sp) #elif defined(CONFIG_X86_64) /* Old x86 64-bit */ /* The IP is on the stack, so we don't need to check it separately. * Instead, we need to prevent Ksplice from patching thread_return. */ extern const char thread_return[]; EXTRACT_SYMBOL(thread_return); #define KSPLICE_IP(x) ((unsigned long)thread_return) #define KSPLICE_SP(x) ((x)->thread.rsp) #else /* Old x86 32-bit */ #define KSPLICE_IP(x) ((x)->thread.eip) #define KSPLICE_SP(x) ((x)->thread.esp) #endif /* __ASM_X86_PROCESSOR_H */ #ifndef CONFIG_FUNCTION_DATA_SECTIONS #include "udis86.h" #ifdef CONFIG_FTRACE #include #include extern ftrace_func_t ftrace_trace_function; EXTRACT_SYMBOL(ftrace_trace_function); #endif /* CONFIG_FTRACE */ #define N_BITS(n) ((n) < sizeof(long) * 8 ? ~(~0L << (n)) : ~0L) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) /* 91768d6c2bad0d2766a166f13f2f57e197de3458 was after 2.6.19 */ #if defined(_I386_BUG_H) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) || \ defined(CONFIG_DEBUG_BUGVERBOSE)) && \ !defined(do_each_thread_ve) /* OpenVZ */ /* 38326f786cf4529a86b1ccde3aa17f4fa7e8472a was after 2.6.10 */ /* ud2 means BUG(). On old i386 kernels, it is followed by 2 bytes and then a 4-byte relocation; and is not disassembler-friendly. */ struct bug_frame { unsigned char ud2[2]; unsigned short line; char *filename; } __attribute__((packed)); #define KSPLICE_USE_BUG_FRAME #elif defined(__ASM_X8664_BUG_H) #define KSPLICE_USE_BUG_FRAME #endif #endif /* LINUX_VERSION_CODE */ static abort_t compare_instructions(struct ksplice_mod_change *change, struct ksplice_section *sect, const struct ksplice_reloc **fingerp, const unsigned char *run_start, const unsigned char *run, const unsigned char *pre, struct ud *run_ud, struct ud *pre_ud, enum run_pre_mode mode); static abort_t compare_operands(struct ksplice_mod_change *change, struct ksplice_section *sect, const struct ksplice_reloc **fingerp, const unsigned char *run_start, const unsigned char *run, const unsigned char *pre, struct ud *run_ud, struct ud *pre_ud, int opnum, enum run_pre_mode mode); static uint8_t ud_operand_len(struct ud_operand *operand); static uint8_t ud_prefix_len(struct ud *ud); static long ud_operand_lval(struct ud_operand *operand); static int next_run_byte(struct ud *ud); static bool is_nop(struct ud *ud, const unsigned char *addr); static bool is_unconditional_jump(struct ud *ud); static bool is_mcount_call(struct ud *ud, const unsigned char *addr); static void initialize_ksplice_ud(struct ud *ud); static abort_t arch_run_pre_cmp(struct ksplice_mod_change *change, struct ksplice_section *sect, unsigned long run_addr, struct list_head *safety_records, enum run_pre_mode mode) { abort_t ret; const unsigned char *run, *pre, *run_start, *pre_start, *safety_start; /* struct ud is big so we avoid putting it on the stack. This * is safe because we are holding module_mutex. */ static struct ud pre_ud, run_ud; const unsigned char **match_map; const struct ksplice_reloc *finger; unsigned long pre_offset, run_offset; bool run_unconditional = false; bool pre_nop = true, run_nop = true; if (sect->size == 0) return NO_MATCH; pre_start = (const unsigned char *)sect->address; run_start = (const unsigned char *)run_addr; finger = init_reloc_search(change, sect); run = run_start; pre = pre_start; initialize_ksplice_ud(&pre_ud); ud_set_input_buffer(&pre_ud, (unsigned char *)pre, sect->size); initialize_ksplice_ud(&run_ud); ud_set_input_hook(&run_ud, next_run_byte); ud_set_user_opaque_data(&run_ud, (unsigned char *)run_addr); safety_start = run_start; match_map = vmalloc(sizeof(*match_map) * sect->size); if (match_map == NULL) return OUT_OF_MEMORY; memset(match_map, 0, sizeof(*match_map) * sect->size); match_map[0] = run_start; sect->match_map = match_map; sect->unmatched = 1; while (1) { if (pre_nop && ud_disassemble(&pre_ud) == 0) { /* Ran out of pre bytes to match; we're done! */ unsigned long safety_offset = run - safety_start; if (sect->unmatched != 0) { if (mode == RUN_PRE_DEBUG) ksdebug(change, "%d unmatched jumps\n", sect->unmatched); ret = NO_MATCH; goto out; } ret = create_safety_record(change, sect, safety_records, (unsigned long)safety_start, safety_offset); goto out; } if (run_nop && ud_disassemble(&run_ud) == 0) { ret = NO_MATCH; goto out; } pre_nop = is_nop(&pre_ud, pre) || is_mcount_call(&pre_ud, pre); run_nop = is_nop(&run_ud, run) || is_mcount_call(&run_ud, run); if (pre_nop && !run_nop) { if (mode == RUN_PRE_DEBUG) { ksdebug(change, "| nop: "); print_bytes(change, run, 0, pre, ud_insn_len(&pre_ud)); } pre += ud_insn_len(&pre_ud); continue; } if (run_nop && !pre_nop) { if (mode == RUN_PRE_DEBUG) { ksdebug(change, "| nop: "); print_bytes(change, run, ud_insn_len(&run_ud), pre, 0); } run += ud_insn_len(&run_ud); continue; } if (run_nop && pre_nop) { ret = compare_instructions(change, sect, &finger, run_start, run, pre, &run_ud, &pre_ud, RUN_PRE_SILENT); if (ret != OK) { if (mode == RUN_PRE_DEBUG) { ksdebug(change, "| nop: "); print_bytes(change, run, ud_insn_len(&run_ud), pre, ud_insn_len(&pre_ud)); } run += ud_insn_len(&run_ud); pre += ud_insn_len(&pre_ud); continue; } else if (ret != NO_MATCH && ret != OK) { goto out; } } pre_offset = pre - pre_start; if (match_map[pre_offset] == NULL) { match_map[pre_offset] = run; } else if (match_map[pre_offset] == run) { sect->unmatched--; } else { /* There is a discontinuity in the match map. Check that the last instruction was an unconditional change of control */ if (!run_unconditional) { ksdebug(change, "<--[No unconditional change " "of control at control transfer point " "%lx]\n", pre_offset); ret = NO_MATCH; goto out; } if (mode == RUN_PRE_DEBUG) ksdebug(change, " [Moving run pointer for %lx " "from %lx to %lx]\n", pre_offset, (unsigned long)(run - run_start), (unsigned long)(match_map[pre_offset] - run_start)); /* Create a safety_record for the block just matched */ ret = create_safety_record(change, sect, safety_records, (unsigned long)safety_start, run - safety_start); if (ret != OK) goto out; /* We re-initialize the run ud structure because it may have cached upcoming bytes */ run = match_map[pre_offset]; initialize_ksplice_ud(&run_ud); ud_set_input_hook(&run_ud, next_run_byte); ud_set_user_opaque_data(&run_ud, (unsigned char *)run); safety_start = run; if (ud_disassemble(&run_ud) == 0) { ret = NO_MATCH; goto out; } sect->unmatched--; } run_offset = run - run_start; run_unconditional = is_unconditional_jump(&run_ud); run_nop = true; pre_nop = true; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) && \ defined(KSPLICE_USE_BUG_FRAME) /* 91768d6c2bad0d2766a166f13f2f57e197de3458 was after 2.6.19 */ if (run_ud.mnemonic == pre_ud.mnemonic && run_ud.mnemonic == UD_Iud2) { const struct bug_frame *pre_bug = (const struct bug_frame *)pre, *run_bug = (const struct bug_frame *)run; const struct ksplice_reloc *r; ret = lookup_reloc(change, &finger, (unsigned long)&pre_bug->filename, &r); if (ret == NO_MATCH) { if (mode == RUN_PRE_INITIAL) ksdebug(change, "Unrecognized ud2\n"); goto out; } if (ret != OK) goto out; ret = handle_reloc(change, sect, r, (unsigned long)&run_bug->filename, mode); if (ret != OK) goto out; /* If there's a relocation, then it's a BUG? */ if (mode == RUN_PRE_DEBUG) { ksdebug(change, "[BUG?: "); print_bytes(change, run + sizeof(run_bug->ud2), sizeof(*run_bug), pre + sizeof(pre_bug->ud2), sizeof(*pre_bug)); ksdebug(change, "] "); } pre += sizeof(*pre_bug); run += sizeof(*run_bug); ud_input_skip(&run_ud, sizeof(*run_bug) - sizeof(run_bug->ud2)); ud_input_skip(&pre_ud, sizeof(*pre_bug) - sizeof(pre_bug->ud2)); continue; } #endif /* LINUX_VERSION_CODE && KSPLICE_USE_BUG_FRAME */ #ifdef CONFIG_XEN if (run_ud.mnemonic == pre_ud.mnemonic && run_ud.mnemonic == UD_Iud2) { unsigned char bytes[3]; unsigned char prefix[3] = { 0x78, 0x65, 0x6e }; if (probe_kernel_read(bytes, (void *)run + 2, 3) != -EFAULT && pre - pre_start < sect->size && memcmp(bytes, prefix, 3) == 0 && memcmp(pre + 2, prefix, 3) == 0) { /* Exception for XEN_EMULATE_PREFIX */ run += 5; pre += 5; ud_input_skip(&run_ud, 3); ud_input_skip(&pre_ud, 3); continue; } } #endif /* CONFIG_XEN */ ret = compare_instructions(change, sect, &finger, run_start, run, pre, &run_ud, &pre_ud, mode); if (ret != OK) goto out; run += ud_insn_len(&run_ud); pre += ud_insn_len(&pre_ud); } out: if (ret != OK || mode != RUN_PRE_FINAL) { vfree(match_map); sect->match_map = NULL; } return ret; } static abort_t compare_instructions(struct ksplice_mod_change *change, struct ksplice_section *sect, const struct ksplice_reloc **fingerp, const unsigned char *run_start, const unsigned char *run, const unsigned char *pre, struct ud *run_ud, struct ud *pre_ud, enum run_pre_mode mode) { abort_t ret; int i; bool found_bug_entry = false; const unsigned char *pre_start = (const unsigned char *)sect->address; unsigned long pre_offset = pre - pre_start; const struct ksplice_reloc *r; if (mode == RUN_PRE_DEBUG) { ksdebug(change, "| "); print_bytes(change, run, ud_insn_len(run_ud), pre, ud_insn_len(pre_ud)); } if (run_ud->mnemonic != pre_ud->mnemonic) { if (mode == RUN_PRE_DEBUG) ksdebug(change, "mnemonic mismatch: %s %s\n", ud_lookup_mnemonic(run_ud->mnemonic), ud_lookup_mnemonic(pre_ud->mnemonic)); return NO_MATCH; } if (run_ud->mnemonic == UD_Iinvalid) { ksdebug(change, "Unrecognized opcode at %s+%lx\n", sect->symbol->label, pre_offset); return UNEXPECTED; } while (1) { ret = lookup_reloc(change, fingerp, (unsigned long)pre, &r); if (ret == NO_MATCH) break; else if (ret != OK) return ret; else if (r->howto->size != 0) break; if (r->howto->type == KSPLICE_HOWTO_BUG) found_bug_entry = true; if (mode == RUN_PRE_DEBUG) { if (r->howto->type == KSPLICE_HOWTO_EXTABLE) ksdebug(change, "[ex] "); if (r->howto->type == KSPLICE_HOWTO_BUG) ksdebug(change, "[bug] "); if (r->howto->type == KSPLICE_HOWTO_SYMBOL) ksdebug(change, "[sym] "); } ret = handle_reloc(change, sect, r, (unsigned long)run, mode); if (ret != OK) return ret; (*fingerp)++; } #if defined(CONFIG_X86_64) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) /* 91768d6c2bad0d2766a166f13f2f57e197de3458 was after 2.6.19 */ #else /* !CONFIG_X86_64 || LINUX_VERSION_CODE >= */ #ifndef do_each_thread_ve /* OpenVZ */ if (run_ud->mnemonic == UD_Iud2 && !found_bug_entry) { if (strcmp(change->target_name, "kvm_intel") == 0 || strcmp(change->target_name, "kvm_amd") == 0) { /* KVM has ud2a bugs without a bug table entry. */ if (mode == RUN_PRE_DEBUG) ksdebug(change, "[kvm ud2]"); } else { ksdebug(change, "Unexpected ud2\n"); return NO_MATCH; } } #endif /* do_each_thread_ve */ #endif /* CONFIG_X86_64 && LINUX_VERSION_CODE */ for (i = 0; i < ARRAY_SIZE(run_ud->operand); i++) { ret = compare_operands(change, sect, fingerp, run_start, run, pre, run_ud, pre_ud, i, mode); if (ret != OK) return ret; } return OK; } static abort_t compare_operands(struct ksplice_mod_change *change, struct ksplice_section *sect, const struct ksplice_reloc **fingerp, const unsigned char *run_start, const unsigned char *run, const unsigned char *pre, struct ud *run_ud, struct ud *pre_ud, int opnum, enum run_pre_mode mode) { abort_t ret; int i; const unsigned char *pre_start = (const unsigned char *)sect->address; unsigned long pre_offset = pre - pre_start; unsigned long run_offset = run - run_start; struct ud_operand *run_op = &run_ud->operand[opnum]; struct ud_operand *pre_op = &pre_ud->operand[opnum]; uint8_t run_off = ud_prefix_len(run_ud); uint8_t pre_off = ud_prefix_len(pre_ud); const unsigned char **match_map = sect->match_map; const struct ksplice_reloc *r; for (i = 0; i < opnum; i++) { run_off += ud_operand_len(&run_ud->operand[i]); pre_off += ud_operand_len(&pre_ud->operand[i]); } if (run_op->type != pre_op->type) { if (mode == RUN_PRE_DEBUG) ksdebug(change, "type mismatch: %d %d\n", run_op->type, pre_op->type); return NO_MATCH; } if (run_op->base != pre_op->base) { if (mode == RUN_PRE_DEBUG) ksdebug(change, "base mismatch: %d %d\n", run_op->base, pre_op->base); return NO_MATCH; } if (run_op->index != pre_op->index) { if (mode == RUN_PRE_DEBUG) ksdebug(change, "index mismatch: %d %d\n", run_op->index, pre_op->index); return NO_MATCH; } if (run_op->type == UD_OP_PTR && run_op->lval.ptr.seg != pre_op->lval.ptr.seg) { if (mode == RUN_PRE_DEBUG) ksdebug(change, "segment mismatch: %d %d\n", run_op->lval.ptr.seg, pre_op->lval.ptr.seg); return NO_MATCH; } if (ud_operand_len(run_op) == 0 && ud_operand_len(pre_op) == 0) return OK; ret = lookup_reloc(change, fingerp, (unsigned long)(pre + pre_off), &r); if (ret == OK) { struct ksplice_reloc run_reloc = *r; struct ksplice_reloc_howto run_howto = *r->howto; unsigned int run_reloc_len = ud_operand_len(run_op); unsigned int pre_reloc_len = ud_operand_len(pre_op); if (run_op->type == UD_OP_PTR) { /* Adjust for reloc length != operand length for instructions take a segment:offset operand */ run_reloc_len -= 2; pre_reloc_len -= 2; } run_reloc.howto = &run_howto; if (r->howto->size != pre_reloc_len) { ksdebug(change, "ksplice_h: run-pre: reloc size %d " "differs from disassembled size %d\n", r->howto->size, pre_reloc_len); return NO_MATCH; } if (r->howto->size != run_reloc_len && (r->howto->dst_mask != N_BITS(r->howto->size * 8) || r->howto->rightshift != 0)) { /* Reloc types unsupported with differing reloc sizes */ ksdebug(change, "ksplice_h: reloc: invalid flags for a " "relocation with size changed\n"); ksdebug(change, "%ld %u\n", r->howto->dst_mask, r->howto->rightshift); return UNEXPECTED; } /* adjust for differing relocation size */ run_howto.size = run_reloc_len; if (r->howto->size != run_howto.size) run_howto.dst_mask = N_BITS(run_howto.size * 8); run_reloc.insn_addend += pre_reloc_len - run_reloc_len; ret = handle_reloc(change, sect, &run_reloc, (unsigned long)(run + run_off), mode); if (ret != OK) { if (mode == RUN_PRE_DEBUG) ksdebug(change, "Matching failure at offset " "%lx\n", pre_offset); return ret; } /* This operand is a successfully processed relocation */ return OK; } else if (ret != NO_MATCH) { return ret; } if (pre_op->type == UD_OP_JIMM) { /* Immediate jump without a relocation */ const unsigned char *pre_target = pre + ud_insn_len(pre_ud) + ud_operand_lval(pre_op); const unsigned char *run_target = run + ud_insn_len(run_ud) + ud_operand_lval(run_op); if (pre_target >= pre_start && pre_target < pre_start + sect->size) { /* Jump within the current function. Check it's to a corresponding place */ unsigned long new_pre_offset = pre_target - pre_start; unsigned long new_run_offset = run_target - run_start; if (mode == RUN_PRE_DEBUG) ksdebug(change, "[Jumps: pre=%lx run=%lx " "pret=%lx runt=%lx] ", pre_offset, run_offset, new_pre_offset, new_run_offset); if (match_map[pre_target - pre_start] != NULL && match_map[pre_target - pre_start] != run_target) { ksdebug(change, "<--[Jumps to nonmatching " "locations]\n"); return NO_MATCH; } else if (match_map[pre_target - pre_start] == NULL) { match_map[pre_target - pre_start] = run_target; sect->unmatched++; } return OK; } else if (pre_target == run_target) { /* Paravirt-inserted pcrel jump; OK! */ return OK; } else { if (mode == RUN_PRE_DEBUG) { ksdebug(change, "<--Different operands!\n"); ksdebug(change, "%lx %lx %lx %lx %x %lx %lx " "%lx\n", (unsigned long)pre_start, (unsigned long)pre_target, (unsigned long)pre_start + sect->size, (unsigned long)pre, ud_insn_len(pre_ud), sect->size, ud_operand_lval(pre_op), (unsigned long)run_target); } return NO_MATCH; } } else if (ud_operand_len(pre_op) == ud_operand_len(run_op) && memcmp(pre + pre_off, run + run_off, ud_operand_len(run_op)) == 0) { return OK; } else { if (mode == RUN_PRE_DEBUG) ksdebug(change, "<--Different operands!\n"); return NO_MATCH; } } static void initialize_ksplice_ud(struct ud *ud) { ud_init(ud); ud_set_mode(ud, BITS_PER_LONG); ud_set_syntax(ud, NULL); ud_set_pc(ud, 0); ud_set_vendor(ud, UD_VENDOR_ANY); } #ifdef CONFIG_FTRACE static bool is_mcount_call(struct ud *ud, const unsigned char *addr) { const void *target = addr + ud_insn_len(ud) + ud_operand_lval(&ud->operand[0]); if (ud->mnemonic == UD_Icall && (target == mcount || target == ftrace_trace_function)) return true; return false; } #else /* !CONFIG_FTRACE */ static bool is_mcount_call(struct ud *ud, const unsigned char *addr) { return false; } #endif /* CONFIG_FTRACE */ static bool is_nop(struct ud *ud, const unsigned char *addr) { switch (ud->mnemonic) { case UD_Inop: return true; case UD_Imov: case UD_Ixchg: return ud->dis_mode == 32 && ud->operand[0].type == UD_OP_REG && ud->operand[1].type == UD_OP_REG && ud->operand[2].type == UD_NONE && ud->operand[0].base == ud->operand[1].base; case UD_Ilea: return ud->dis_mode == 32 && ud->operand[0].type == UD_OP_REG && ud->operand[1].type == UD_OP_MEM && ((ud->operand[1].base == ud->operand[0].base && ud->operand[1].index == UD_NONE) || (ud->operand[1].base == UD_NONE && ud->operand[1].index == ud->operand[0].base && ud->operand[1].scale == 0)) && ud_operand_lval(&ud->operand[1]) == 0 && ud->operand[2].type == UD_NONE; case UD_Ijmp: /* jmp +N followed by N 0x90s is a NOP */ if (ud->operand[0].type == UD_OP_JIMM && ud->operand[1].type == UD_NONE && ud->operand[2].type == UD_NONE && ud_operand_len(&ud->operand[0]) == 1) { /* struct ud is big so we avoid putting it on the stack. * This is safe because we are holding module_mutex. */ static struct ud temp_ud; int len = ud_operand_lval(&ud->operand[0]); int i; if (len < 0 || len > 13) return false; initialize_ksplice_ud(&temp_ud); ud_set_input_hook(&temp_ud, next_run_byte); ud_set_user_opaque_data(&temp_ud, (unsigned char *)addr + ud_insn_len(ud)); for (i = 0; i < len; i++) { if (ud_disassemble(&temp_ud) == 0) return false; if (temp_ud.mnemonic != UD_Inop) return false; } return true; } default: return false; } } static bool is_unconditional_jump(struct ud *ud) { switch (ud->mnemonic) { case UD_Ijmp: case UD_Iret: case UD_Iretf: case UD_Iiretw: case UD_Iiretd: case UD_Iiretq: case UD_Isysexit: case UD_Isysret: case UD_Isyscall: case UD_Isysenter: return true; default: return false; } } static uint8_t ud_operand_len(struct ud_operand *operand) { if (operand->type == UD_OP_MEM) return operand->offset / 8; if (operand->type == UD_OP_REG) return 0; return operand->size / 8; } static uint8_t ud_prefix_len(struct ud *ud) { int len = ud_insn_len(ud); int i; for (i = 0; i < ARRAY_SIZE(ud->operand); i++) len -= ud_operand_len(&ud->operand[i]); return len; } static long ud_operand_lval(struct ud_operand *operand) { switch (operand->type == UD_OP_MEM ? operand->offset : operand->size) { case 8: return operand->lval.sbyte; case 16: return operand->lval.sword; case 32: return operand->lval.sdword; case 64: return operand->lval.sqword; default: return 0; } } static int next_run_byte(struct ud *ud) { unsigned char byte; if (probe_kernel_read(&byte, ud_get_user_opaque_data(ud), 1) == -EFAULT) return UD_EOI; ud_set_user_opaque_data(ud, ud_get_user_opaque_data(ud) + 1); return byte; } #endif /* !CONFIG_FUNCTION_DATA_SECTIONS */ static struct ksplice_symbol trampoline_symbol = { .name = NULL, .label = "", }; static const struct ksplice_reloc_howto trampoline_howto = { .type = KSPLICE_HOWTO_RELOC, .pcrel = 1, .size = 4, .dst_mask = 0xffffffffL, .rightshift = 0, .signed_addend = 1, }; static const struct ksplice_reloc trampoline_reloc = { .symbol = &trampoline_symbol, .insn_addend = -4, .target_addend = 0, .howto = &trampoline_howto, }; static abort_t trampoline_target(struct ksplice_mod_change *change, unsigned long addr, unsigned long *new_addr) { abort_t ret; unsigned char byte; if (probe_kernel_read(&byte, (void *)addr, sizeof(byte)) == -EFAULT) return NO_MATCH; if (byte != 0xe9) return NO_MATCH; ret = read_reloc_value(change, &trampoline_reloc, addr + 1, new_addr); if (ret != OK) return ret; *new_addr += addr + 1; return OK; } static abort_t prepare_trampoline(struct ksplice_mod_change *change, struct ksplice_patch *p) { p->size = 5; ((unsigned char *)p->contents)[0] = 0xe9; return write_reloc_value(change, &trampoline_reloc, (unsigned long)p->contents + 1, p->repladdr - (p->oldaddr + 1)); } static abort_t handle_paravirt(struct ksplice_mod_change *change, unsigned long pre_addr, unsigned long run_addr, int *matched) { unsigned char run[5], pre[5]; *matched = 0; if (probe_kernel_read(&run, (void *)run_addr, sizeof(run)) == -EFAULT || probe_kernel_read(&pre, (void *)pre_addr, sizeof(pre)) == -EFAULT) return OK; if ((run[0] == 0xe8 && pre[0] == 0xe8) || (run[0] == 0xe9 && pre[0] == 0xe9)) if (run_addr + 1 + *(int32_t *)&run[1] == pre_addr + 1 + *(int32_t *)&pre[1]) *matched = 5; return OK; } static bool valid_stack_ptr(const struct thread_info *tinfo, const void *p) { return p > (const void *)tinfo && p <= (const void *)tinfo + THREAD_SIZE - sizeof(long); } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) static bool virtual_address_mapped(unsigned long addr) { pgd_t *pgd; #ifdef pud_page pud_t *pud; #endif /* pud_page */ pmd_t *pmd; pte_t *pte; #ifdef KSPLICE_STANDALONE if (!bootstrapped) return true; #endif /* KSPLICE_STANDALONE */ pgd = pgd_offset_k(addr); if (!pgd_present(*pgd)) return false; #ifdef pud_page pud = pud_offset(pgd, addr); if (!pud_present(*pud)) return false; pmd = pmd_offset(pud, addr); #else /* pud_page */ pmd = pmd_offset(pgd, addr); #endif /* pud_page */ if (!pmd_present(*pmd)) return false; if (pmd_large(*pmd)) return true; pte = pte_offset_kernel(pmd, addr); if (!pte_present(*pte)) return false; return true; } #endif /* LINUX_VERSION_CODE */ ksplice-0.9.9/kmodsrc/ksplice.h0000644000000000000000000002124511244274432015135 0ustar rootroot#include /** * struct ksplice_symbol - Ksplice's analogue of an ELF symbol * @name: The ELF name of the symbol * @label: A unique Ksplice name for the symbol * @candidate_vals: A linked list of possible values for the symbol, or NULL * @value: The value of the symbol (valid when vals is NULL) **/ struct ksplice_symbol { const char *name; const char *label; /* private: */ struct list_head *candidate_vals; unsigned long value; }; /** * struct ksplice_reloc - Ksplice's analogue of an ELF relocation * @blank_addr: The address of the relocation's storage unit * @symbol: The ksplice_symbol associated with this relocation * @howto: The information regarding the relocation type * @insn_addend: The part of the ELF addend resulting from quirks of * the instruction one of whose operands is the relocation. * For example, this is -4 on x86 pc-relative jumps. * @target_addend: The rest of the ELF addend. This is equal to the offset * against the symbol that the relocation refers to. **/ struct ksplice_reloc { unsigned long blank_addr; struct ksplice_symbol *symbol; const struct ksplice_reloc_howto *howto; long insn_addend; long target_addend; }; enum ksplice_reloc_howto_type { KSPLICE_HOWTO_RELOC, KSPLICE_HOWTO_RELOC_PATCH, KSPLICE_HOWTO_DATE, KSPLICE_HOWTO_TIME, KSPLICE_HOWTO_BUG, KSPLICE_HOWTO_EXTABLE, KSPLICE_HOWTO_SYMBOL, }; /** * struct ksplice_reloc_howto - Ksplice's relocation type information * @type: The type of the relocation * @pcrel: Is the relocation PC relative? * @size: The size, in bytes, of the item to be relocated * @dst_mask: Bitmask for which parts of the instruction or data are * replaced with the relocated value * (based on dst_mask from GNU BFD's reloc_howto_struct) * @rightshift: The value the final relocation is shifted right by; * used to drop unwanted data from the relocation * (based on rightshift from GNU BFD's reloc_howto_struct) * @signed_addend: Should the addend be interpreted as a signed value? **/ struct ksplice_reloc_howto { enum ksplice_reloc_howto_type type; int pcrel; int size; long dst_mask; unsigned int rightshift; int signed_addend; }; #if BITS_PER_LONG == 32 #define KSPLICE_CANARY 0x77777777UL #elif BITS_PER_LONG == 64 #define KSPLICE_CANARY 0x7777777777777777UL #endif /* BITS_PER_LONG */ /** * struct ksplice_section - Ksplice's analogue of an ELF section * @symbol: The ksplice_symbol associated with this section * @size: The length, in bytes, of this section * @address: The address of the section * @flags: Flags indicating the type of the section, whether or * not it has been matched, etc. **/ struct ksplice_section { struct ksplice_symbol *symbol; unsigned long address; unsigned long size; unsigned int flags; const unsigned char **match_map; int unmatched; }; #define KSPLICE_SECTION_TEXT 0x00000001 #define KSPLICE_SECTION_RODATA 0x00000002 #define KSPLICE_SECTION_DATA 0x00000004 #define KSPLICE_SECTION_STRING 0x00000008 #define KSPLICE_SECTION_MATCH_DATA_EARLY 0x00000100 #define KSPLICE_SECTION_MATCHED 0x10000000 #define MAX_TRAMPOLINE_SIZE 5 enum ksplice_patch_type { KSPLICE_PATCH_TEXT, KSPLICE_PATCH_DATA, KSPLICE_PATCH_EXPORT, }; /** * struct ksplice_patch - A replacement that Ksplice should perform * @oldaddr: The address of the obsolete function or structure * @repladdr: The address of the replacement function * @type: The type of the ksplice patch * @size: The size of the patch * @contents: The bytes to be installed at oldaddr * @vaddr The address of the page mapping used to write at oldaddr * @saved: The bytes originally at oldaddr which were * overwritten by the patch **/ struct ksplice_patch { unsigned long oldaddr; unsigned long repladdr; enum ksplice_patch_type type; unsigned int size; void *contents; /* private: */ void *vaddr; void *saved; }; #ifdef KSPLICE_STANDALONE struct ksplice_system_map { const char *label; unsigned long nr_candidates; const unsigned long *candidates; }; #endif /* KSPLICE_STANDALONE */ #ifdef __KERNEL__ #include #include #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) /* 6e21828743247270d09a86756a0c11702500dbfb was after 2.6.18 */ #define bool _Bool #define false 0 #define true 1 #endif /* LINUX_VERSION_CODE */ #if defined(CONFIG_PARAVIRT) && defined(CONFIG_X86_64) && \ LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) && \ LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) /* Linux 2.6.25 and 2.6.26 apply paravirt replacements to the core * kernel but not modules on x86-64. If we are patching the core * kernel, we need to apply the same replacements to our update * modules in order for run-pre matching to succeed. */ #define KSPLICE_NEED_PARAINSTRUCTIONS 1 #endif /* KSPLICE_NEED_PARAINSTRUCTIONS */ #define _PASTE(x, y) x##y #define PASTE(x, y) _PASTE(x, y) #define KSPLICE_UNIQ(s) PASTE(s##_, KSPLICE_MID) #define KSPLICE_KID_UNIQ(s) PASTE(s##_, KSPLICE_KID) #ifdef KSPLICE_STANDALONE #define init_ksplice_mod_change KSPLICE_KID_UNIQ(init_ksplice_mod_change) #define cleanup_ksplice_mod_change KSPLICE_KID_UNIQ(cleanup_ksplice_mod_change) #endif /** * struct ksplice_module_list_entry - A record of a ksplice_mod_change's target * @target_mod_name: The name of the ksplice_mod_change's target module * @new_code_mod_name: The name of the ksplice_mod_change's new_code module * @applied: Whether the ksplice_mod_change was applied or not (this * will be false for ksplice_mod_changes patching targets * that are not loaded when the partial flag is set) **/ struct ksplice_module_list_entry { const char *target_mod_name; const char *new_code_mod_name; const char *kid; bool applied; /* private: */ struct list_head update_list; /* list head for this is per-update */ struct list_head list; /* list head for this is global */ }; /* List of all ksplice modules and the module they patch */ extern struct list_head ksplice_modules; /* There are two actions, apply and reverse */ #define KS_ACTIONS 2 enum ksplice_action { KS_APPLY, KS_REVERSE, }; /** * struct ksplice_hooks - Hooks to be run during an action (apply or reverse) * @pre: Runs before the action; * may return nonzero to abort the action * @check: Runs inside stop_machine before the action; * may return nonzero to abort the action * @intra: Runs inside stop_machine during the action * @post: Runs after the action is successfully performed * @fail: Runs if the action is aborted for any reason */ struct ksplice_hooks { const typeof(int (*)(void)) *pre, *pre_end, *check, *check_end; const typeof(void (*)(void)) *intra, *intra_end, *post, *post_end, *fail, *fail_end; }; /** * struct ksplice_code - Ksplice metadata for an object * @relocs: The Ksplice relocations for the object * @symbols: The Ksplice symbols for the object * @sections: The Ksplice sections for the object **/ struct ksplice_code { struct ksplice_reloc *relocs, *relocs_end; struct ksplice_section *sections, *sections_end; struct ksplice_symbol *symbols, *symbols_end; #ifdef KSPLICE_NEED_PARAINSTRUCTIONS struct paravirt_patch_site *parainstructions, *parainstructions_end; #endif /* KSPLICE_NEED_PARAINSTRUCTIONS */ #ifdef KSPLICE_STANDALONE struct ksplice_system_map *system_map, *system_map_end; #endif /* KSPLICE_STANDALONE */ }; /** * struct ksplice_mod_change - Data for one module modified by a Ksplice update * @name: The name of the new_code module for the change * @kid: The Ksplice unique identifier for the change * @target_name: The name of the module modified by the change * @new_code_mod: The new_code module for the change * @old_code: The old code for run-pre matching * @new_code: The new code to switch to * @patches: The function replacements in the change * @patches_end: The end pointer for patches array * @hooks: Hooks to be run during apply and reverse * @update: The atomic update the change is part of * @target: The module modified by the change * @safety_records: The ranges of addresses that must not be on a * kernel stack for the patch to apply safely **/ struct ksplice_mod_change { const char *name; const char *kid; const char *target_name; #ifdef KSPLICE_STANDALONE unsigned long map_printk; #endif /* KSPLICE_STANDALONE */ struct module *new_code_mod; struct ksplice_code old_code, new_code; struct ksplice_patch *patches, *patches_end; struct ksplice_hooks hooks[KS_ACTIONS]; /* private: */ struct update *update; struct module *target; struct list_head temp_labelvals; struct list_head safety_records; struct list_head list; }; int init_ksplice_mod_change(struct ksplice_mod_change *change); void cleanup_ksplice_mod_change(struct ksplice_mod_change *change); #endif /* __KERNEL__ */ ksplice-0.9.9/ksplice-view.in0000644000000000000000000001000711244274432014614 0ustar rootroot#!/usr/bin/perl # Copyright (C) 2007-2009 Ksplice, Inc. # Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA # 02110-1301, USA. use strict; use warnings; use lib 'KSPLICE_DATA_DIR'; use Ksplice; my ($kid, $mid, $module, $update, $file); GetOptions(@common_options, "id=s" => \$kid, "file=s" => \$file) or pod2usage(1); pod2usage(1) if($help || scalar(@ARGV) != 0); my $actions = (defined $kid) + (defined $file); pod2usage(1) if($actions > 1); view_kid() if(defined $kid); view_file() if(defined $file); view_list() if($actions == 0); exit(0); sub view_kid { $kid =~ s/^ksplice[_-]//; $kid =~ s/[-_].*$//; # In case we got an mid instead $update = "ksplice_$kid"; if(!update_loaded($kid)) { print "Ksplice id $kid is not present in the kernel\n"; exit(0); } my $stage = get_stage($kid); print "Ksplice id $kid is present in the kernel and is $stage.\n\n"; my $source_diff = get_patch($kid); return if($source_diff eq ""); print "Here is the source code patch associated with this update:\n"; print $source_diff; } sub view_file { chdir(unpack_update($file)); open(PATCH, '<', "patch") or die $!; local $/; print ; close(PATCH); } sub show_kid { my ($kid) = @_; if ($Verbose::level < 0) { print "$kid\n"; } else { my $desc = get_short_description($kid); if (defined($desc)) { print "$kid: $desc"; } else { print "$kid: no description available\n"; } } } sub view_list { foreach(split(/\n/, runstr("lsmod"))) { next unless my ($mid) = m/^ksplice_(\S*)\s/; $module = "ksplice_$mid"; ($kid = $mid) =~ s/[-_].*$//; next unless (-e "/sys/module/$module/ksplice/stage"); open STAGE, '<', "/sys/module/$module/ksplice/stage" or die "Unable to read stage file; are you root?"; show_kid($kid) if( eq "applied\n"); close STAGE; } if (-e "/sys/kernel/ksplice") { chdir("/sys/kernel/ksplice"); foreach $update (glob("*")) { ($kid = $update) =~ s/^ksplice_//; show_kid($kid) if(get_stage($kid) eq "applied"); } } } =head1 NAME ksplice-view - View in-kernel or on-disk Ksplice kernel updates =head1 SYNOPSIS B B B<--id=>I B B<--file=>{I | I} =head1 DESCRIPTION When called with no arguments, B lists the identification tags of all of the Ksplice updates that are currently present in the running kernel, along with their descriptions. B can report about a specific Ksplice update when given the update's identification tag I (if the update is in the kernel) or given the update's tarball filename I or unpacked tree root I (if the update is on disk). =head1 OPTIONS =over 8 =item B<--id=>I Report information about the Ksplice update I currently loaded in the running kernel. =item B<--file=>{I | I} Report information about the Ksplice update on disk as the tarball I or unpacked as the tree I. =item B<-q> Output only the update IDs, one per line, omitting descriptions. =back =head1 SEE ALSO L, L, L =head1 BUGS Please report bugs to . =head1 AUTHORS Jeff Arnold, Anders Kaseorg, and Tim Abbott =head1 COPYRIGHT Copyright (C) 2007-2009 Ksplice, Inc. This is free software and documentation. You can redistribute and/or modify it under the terms of the GNU General Public License, version 2. =cut ksplice-0.9.9/Makefile.ksplice0000644000000000000000000002144611244274432014764 0ustar rootrootksplice-makefile := $(word $(words $(MAKEFILE_LIST)), $(MAKEFILE_LIST)) ksplice-script = $(dir $(ksplice-makefile))ksplice-obj.pl KSPLICE_MODE ?= diff $(if $(filter_out snap diff revert modinst,$(KSPLICE_MODE)), \ $(error Invalid KSPLICE_MODE $(KSPLICE_MODE).)) KSPLICE_ONLY_TARGETS ?= % PHONY := __ksplice: ksplice-extra = $(filter-out $(KSPLICE_EXCLUDE_MATCH),$(filter $(KSPLICE_EXTRA_MATCH),$(lib-y) $(real-objs-m) $(real-objs-y))) ksplice-objs = $(foreach o,$(1),$(o:=.KSPLICE) $(addsuffix .KSPLICE_old_code,$(filter $(ksplice-extra),$(o)))) escsq ?= $(subst ','\'',$(1)) echo-cmd ?= $(if $($(quiet)cmd_$(1)),echo ' $(call escsq,$($(quiet)cmd_$(1)))';) quiet_cmd_ksplice-combine = COMBINE $(@:.KSPLICE=) cmd_ksplice-combine = $(ksplice-script) combine $@ $(filter $(call ksplice-objs,$(ksplice-link-deps)) $(@:.KSPLICE=),$^ $|) quiet_cmd_ksplice-snap = SNAP $(@:.KSPLICE=) cmd_ksplice-snap = $(ksplice-script) snap $@ quiet_cmd_ksplice-diff = DIFF $(@:.KSPLICE=) cmd_ksplice-diff = $(ksplice-script) diff $@ quiet_cmd_ksplice-ignore = IGNORE $(@:.KSPLICE=) cmd_ksplice-ignore = touch $@ quiet_cmd_ksplice-cow = COW $@ cmd_ksplice-cow = cp -a $@ $@.KSPLICE_pre quiet_cmd_ksplice-mod = MOD $(@:$(KSPLICE_KMODSRC)/%.mod.KSPLICE=%) cmd_ksplice-mod = echo $(<:.o.KSPLICE=) > $@; cp -a $< $(<:.KSPLICE=.KSPLICE_new_code) $(<:.KSPLICE=.KSPLICE_old_code) $(KSPLICE_KMODSRC)/ rule_ksplice-mod = if [ -s $< ]; then $(echo-cmd) $(cmd_$(1)); fi quiet_cmd_ksplice-old-code = OLDCODE $(@:.KSPLICE_old_code=) cmd_ksplice-old-code = $(ksplice-script) old_code $@ quiet_cmd_ksplice-freeze = FREEZE $(@:_ksplice-revert_%.KSPLICE_pre=%) cmd_ksplice-freeze = rm -f $(@:_ksplice-revert_%=%) quiet_cmd_ksplice-revert = REVERT $(@:_ksplice-revert_%.KSPLICE_pre=%) cmd_ksplice-revert = touch -r ksplice-revert-stamp $(@:_ksplice-revert_%=%); mv $(@:_ksplice-revert_%=%) $(@:_ksplice-revert_%.KSPLICE_pre=%) quiet_cmd_ksplice-revert-snap = SNAP $(@:_ksplice-revert-snap_%.KSPLICE=%) cmd_ksplice-revert-snap = $(ksplice-script) snap $(@:_ksplice-revert-snap_%=%) quiet_cmd_ksplice-clean = CLEAN $(@:_ksplice-clean_%=%) cmd_ksplice-clean = rm -f $(@:_ksplice-clean_%=%) ifeq ($(obj),) ifneq ($(wildcard include/linux/compile.h),) MAKE += --old-file=include/linux/compile.h endif ifneq ($(filter snap diff,$(KSPLICE_MODE)),) # Makefile.lib must be included before Makefile because they contain # different filechk definitions in 2.6.12. include $(if $(KBUILD_SRC),$(KBUILD_SRC)/)scripts/Makefile.lib endif include $(if $(KBUILD_SRC),$(KBUILD_SRC)/)Makefile ifneq ($(skip-makefile),) PHONY += __ksplice __ksplice: FORCE $(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \ KBUILD_SRC=$(CURDIR) \ KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(ksplice-makefile) \ $(if $(wildcard $(KBUILD_OUTPUT)/include/config/kernel.release),--old-file=include/config/kernel.release) else # skip-makefile CC := ksplice-cc.pl $(CC) CFLAGS_KSPLICE = -ffunction-sections -fdata-sections -ksplice-cflags-api=1 CFLAGS_KERNEL += $(CFLAGS_KSPLICE) CFLAGS_MODULE += $(CFLAGS_KSPLICE) ifeq ($(KSPLICE_MODE),revert) ksplice-revert-dirs = $(vmlinux-alldirs:%=_ksplice_%) ksplice-dirs += $(ksplice-revert-dirs) .INTERMEDIATE $(ksplice-revert-dirs): ksplice-revert-stamp ksplice-revert-stamp: FORCE $(Q)touch $@ endif # KSPLICE_MODE ifneq ($(filter snap diff,$(KSPLICE_MODE)),) ksplice-mods += vmlinux ifdef KSPLICE_BUILD_MODULES ksplice-deps += ksplice_modpost endif ksplice-deps += $(vmlinux-dirs) ksplice-vmlinux-objs = $(if $(vmlinux-all),$(vmlinux-all),$(vmlinux-objs)) $(obj)/vmlinux.o.KSPLICE: ksplice-link-deps = $(ksplice-vmlinux-objs) $(obj)/vmlinux.o.KSPLICE: $(call ksplice-objs,$(ksplice-vmlinux-objs)) FORCE $(call if_changed,ksplice-combine) ksplice-targets += $(obj)/vmlinux.o.KSPLICE $(ksplice-vmlinux-objs:=.KSPLICE): $(vmlinux-dirs) ; PHONY += ksplice_modpost ksplice_modpost: $(vmlinux-dirs) vmlinux $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost endif # KSPLICE_MODE ifeq ($(KSPLICE_MODE),modinst) ksplice-deps += ksplice_modinst PHONY += ksplice_modinst ksplice_modinst: $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst endif # KSPLICE_MODE endif # skip-makefile else # obj ifeq ($(KSPLICE_MODE),revert) -include .config # workaround for missing obj- = subdir/ declarations include $(srctree)/scripts/Makefile.clean ksplice-dirs += $(subdir-ymn:%=_ksplice_%) endif # KSPLICE_MODE ifneq ($(filter snap diff,$(KSPLICE_MODE)),) ifdef KSPLICE_BUILD_MODULES KBUILD_MODULES = 1 endif include $(srctree)/scripts/Makefile.build ksplice-mods += $(obj-m:.o=) ksplice-deps += $(if $(filter $(KSPLICE_ONLY_TARGETS),vmlinux),$(builtin-target:=.KSPLICE) $(lib-target:=.KSPLICE)) ifdef KSPLICE_BUILD_MODULES ksplice-deps += __build endif ksplice-deps += $(subdir-ym) $(always) ifdef builtin-target $(builtin-target:=.KSPLICE): ksplice-link-deps = $(obj-y) $(builtin-target:=.KSPLICE): $(call ksplice-objs,$(obj-y)) FORCE | $(builtin-target) $(call if_changed,ksplice-combine) ksplice-targets += $(builtin-target:=.KSPLICE) endif ifdef lib-target $(lib-target:=.KSPLICE): ksplice-link-deps = $(lib-y) $(lib-target:=.KSPLICE): $(call ksplice-objs,$(lib-y)) FORCE | $(lib-target) $(call if_changed,ksplice-combine) ksplice-targets += $(lib-target:=.KSPLICE) endif $(sort $(multi-used-y:=.KSPLICE) $(multi-used-m:=.KSPLICE)): ksplice-link-deps = $($(@:$(obj)/%.o.KSPLICE=%-objs):%=$(obj)/%) $($(@:$(obj)/%.o.KSPLICE=%-y):%=$(obj)/%) $(sort $(multi-used-y:=.KSPLICE)): $(obj)/%.o.KSPLICE: $(call ksplice-objs,$(multi-objs-y)) FORCE | $(obj)/%.o $(call if_changed,ksplice-combine) $(sort $(multi-used-m:=.KSPLICE)): $(obj)/%.o.KSPLICE: $(call ksplice-objs,$(multi-objs-m)) FORCE | $(obj)/%.o $(call if_changed,ksplice-combine) ksplice-targets += $(sort $(multi-used-y:=.KSPLICE) $(multi-used-m:=.KSPLICE)) ifeq ($(KSPLICE_MODE),snap) $(obj)/%.o.KSPLICE: $(obj)/%.o FORCE $(if $(strip $(wildcard $<.KSPLICE_pre) $(filter $<,$?)), \ $(call cmd,ksplice-snap)) else $(obj)/%.o.KSPLICE: $(obj)/%.o $(call cmd,ksplice-diff) endif $(obj)/%.lds.KSPLICE: $(call cmd,ksplice-ignore) $(sort $(subdir-obj-y:=.KSPLICE)): $(subdir-ym) ; ifeq ($(MAKECMDGOALS),missing-syscalls) cmd = @: endif endif # KSPLICE_MODE endif # obj ifeq ($(skip-makefile),) ifeq ($(KSPLICE_MODE),revert) ksplice-revert-obj := $(wildcard $(obj)/*.KSPLICE_pre) ksplice-revert-files := $(ksplice-revert-obj) ifneq ($(obj),$(src)) ksplice-revert-files += $(wildcard $(src)/*.KSPLICE_pre) endif ksplice-revert-deps := $(ksplice-revert-files:%=_ksplice-revert_%) ksplice-deps += $(ksplice-revert-deps) PHONY += $(ksplice-revert-deps) $(ksplice-revert-deps): FORCE ifdef KSPLICE_SERIES $(call cmd,ksplice-freeze) else $(call cmd,ksplice-revert) endif ksplice-revert-snap-files := $(wildcard $(ksplice-revert-obj:.KSPLICE_pre=.KSPLICE)) ksplice-revert-snap-deps := $(ksplice-revert-snap-files:%=_ksplice-revert-snap_%) ksplice-deps += $(ksplice-revert-snap-deps) PHONY += $(ksplice-revert-snap-deps) $(ksplice-revert-snap-deps): $(ksplice-revert-snap-files:%.KSPLICE=_ksplice-revert_%.KSPLICE_pre) FORCE $(call cmd,ksplice-revert-snap) ksplice-clean-files := $(filter-out $(ksplice-revert-snap-files:.KSPLICE_pre=.KSPLICE_new_code) $(ksplice-revert-snap-files:.KSPLICE_pre=.KSPLICE_old_code),$(wildcard $(obj)/*.KSPLICE_new_code $(obj)/*.KSPLICE_old_code)) ksplice-clean-deps = $(ksplice-clean-files:%=_ksplice-clean_%) ksplice-deps += $(ksplice-clean-deps) PHONY += $(ksplice-clean-deps) $(ksplice-clean-deps): FORCE $(call cmd,ksplice-clean) endif # KSPLICE_MODE ifneq ($(filter snap diff,$(KSPLICE_MODE)),) ksplice-modnames = $(filter $(KSPLICE_ONLY_TARGETS),$(notdir $(ksplice-mods))) ifdef KSPLICE_KMODSRC ksplice-deps += $(ksplice-modnames:%=$(KSPLICE_KMODSRC)/%.mod.KSPLICE) $(KSPLICE_KMODSRC)/%.mod.KSPLICE: $(obj)/%.o.KSPLICE $(Q)$(call rule_ksplice-mod,ksplice-mod) else ksplice-deps += $(ksplice-modnames:%=$(obj)/%.o.KSPLICE) endif .SECONDARY: $(obj)/%.o.KSPLICE $(obj)/%.o.KSPLICE_old_code: $(obj)/%.o.KSPLICE $(call cmd,ksplice-old-code) ifeq ($(KSPLICE_MODE),diff) define ksplice-cow-check $(if $(strip $(1)),$(if $(filter-out %.KSPLICE,$@),$(if $(wildcard $@),$(if $(wildcard $@.KSPLICE_pre),,$(call cmd,ksplice-cow) ))))$(1) endef define ksplice-add-cow-check $(v) = $$(call ksplice-cow-check,$(value $(v))) endef ksplice-cow-eval += $(foreach v,if_changed if_changed_dep if_changed_rule,$(ksplice-add-cow-check)) endif # KSPLICE_MODE ksplice-cmd-files := $(wildcard $(foreach f,$(sort $(ksplice-targets)),$(dir $(f)).$(notdir $(f)).cmd)) ifneq ($(ksplice-cmd-files),) $(ksplice-cmd-files): ; include $(ksplice-cmd-files) endif endif # KSPLICE_MODE PHONY += __ksplice __ksplice: $(ksplice-deps) $(ksplice-dirs) @: build := -f $(ksplice-makefile) obj descend =$(Q)$(MAKE) $(build)=$(1) $(2) PHONY += $(ksplice-dirs) $(ksplice-dirs): $(Q)$(MAKE) $(build)=$(@:_ksplice_%=%) endif # skip-makefile $(eval $(ksplice-cow-eval)) PHONY += FORCE FORCE: .PHONY: $(PHONY) ksplice-0.9.9/Verbose.pm0000644000000000000000000000177111244274432013635 0ustar rootrootpackage Verbose; use strict; use warnings; our $AUTOLOAD; our $level = 0; sub import { my $self = shift; my $minlevel = 0; foreach (@_) { if (m/^:(\d+)$/) { $minlevel = $1; } else { &make_verbose($minlevel, $_, (caller)[0]); } } } sub AUTOLOAD { &make_verbose($AUTOLOAD, (caller)[0]); goto &$AUTOLOAD; } sub debugcall { my ($minlevel, $name, @args) = @_; local $" = ', '; print "+ $name(@args)\n" if ($level >= $minlevel); } sub make_verbose { no strict 'refs'; no warnings qw(redefine prototype); my ($minlevel, $sym, $pkg) = @_; $sym = "${pkg}::$sym" unless $sym =~ /::/; my $name = $sym; $name =~ s/.*::// or $name =~ s/^&//; my ($sref, $call, $proto); if (defined(&$sym)) { $sref = \&$sym; $call = '&$sref'; $proto = prototype $sref; } else { $call = "CORE::$name"; $proto = prototype $call; } $proto = '@' unless defined($proto); my $code = "package $pkg; sub ($proto) { Verbose::debugcall($minlevel, \"$name\", \@_); $call(\@_); }"; *{$sym} = eval($code); } 1; ksplice-0.9.9/objcommon.h0000644000000000000000000002077511244274432014033 0ustar rootroot#include #include #include #include #include #include #include #include #define BITS_PER_LONG LONG_BIT #define _PASTE(x, y) x##y #define PASTE(x, y) _PASTE(x, y) #define DIE do { fprintf(stderr, "ksplice: died at %s:%d\n", __FILE__, __LINE__); abort(); } while(0) #define assert(x) do { if(!(x)) DIE; } while(0) #define align(x, n) ((((x)+(n)-1)/(n))*(n)) #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) #define DECLARE_VEC_TYPE(elt_t, vectype) \ struct vectype { \ elt_t *data; \ size_t size; \ size_t mem_size; \ } /* void vec_init(struct vectype *vec); */ #define vec_init(vec) *(vec) = (typeof(*(vec))) { NULL, 0, 0 } /* void vec_move(struct vectype *dstvec, struct vectype *srcvec); */ #define vec_move(dstvec, srcvec) do { \ typeof(srcvec) _srcvec = (srcvec); \ *(dstvec) = *(_srcvec); \ vec_init(_srcvec); \ } while (0) /* void vec_free(struct vectype *vec); */ #define vec_free(vec) do { \ typeof(vec) _vec1 = (vec); \ free(_vec1->data); \ vec_init(_vec1); \ } while (0) void vec_do_reserve(void **data, size_t *mem_size, size_t newsize); /* void vec_reserve(struct vectype *vec, size_t new_mem_size); */ #define vec_reserve(vec, new_mem_size) do { \ typeof(vec) _vec2 = (vec); \ vec_do_reserve((void **)&_vec2->data, &_vec2->mem_size, \ (new_mem_size)); \ } while (0) /* void vec_resize(struct vectype *vec, size_t new_size); */ #define vec_resize(vec, new_size) do { \ typeof(vec) _vec3 = (vec); \ _vec3->size = (new_size); \ vec_reserve(_vec3, _vec3->size * sizeof(*_vec3->data)); \ } while (0) /* elt_t *vec_grow(struct vectype *vec, size_t n); */ #define vec_grow(vec, n) ({ \ typeof(vec) _vec4 = (vec); \ size_t _n = (n); \ vec_resize(_vec4, _vec4->size + _n); \ _vec4->data + (_vec4->size - _n); \ }) DECLARE_VEC_TYPE(void, void_vec); DECLARE_VEC_TYPE(arelent *, arelentp_vec); DECLARE_VEC_TYPE(asymbol *, asymbolp_vec); DECLARE_VEC_TYPE(asymbol **, asymbolpp_vec); #define DECLARE_HASH_TYPE(elt_t, hashtype, \ hashtype_init, hashtype_free, \ hashtype_lookup) \ struct hashtype { \ struct bfd_hash_table root; \ }; \ \ void hashtype_init(struct hashtype *table); \ void hashtype_free(struct hashtype *table); \ typeof(elt_t) *hashtype_lookup(struct hashtype *table, \ const char *string, \ bfd_boolean create) #ifndef BFD_HASH_TABLE_HAS_ENTSIZE #define bfd_hash_table_init(table, newfunc, entry) \ bfd_hash_table_init(table, newfunc) #endif #define IMPLEMENT_HASH_TYPE(elt_t, hashtype, \ hashtype_init, hashtype_free, \ hashtype_lookup, \ elt_construct) \ \ struct hashtype##_entry { \ struct bfd_hash_entry root; \ typeof(elt_t) val; \ }; \ \ static struct bfd_hash_entry *hashtype##_newfunc( \ struct bfd_hash_entry *entry, \ struct bfd_hash_table *table, \ const char *string) \ { \ if (entry == NULL) { \ entry = bfd_hash_allocate(table, \ sizeof(struct hashtype##_entry)); \ if (entry == NULL) \ return entry; \ } \ entry = bfd_hash_newfunc(entry, table, string); \ typeof(elt_t) *v = \ &container_of(entry, struct hashtype##_entry, \ root)->val; \ elt_construct(v); \ return entry; \ }; \ \ void hashtype_init(struct hashtype *table) \ { \ bfd_hash_table_init(&table->root, hashtype##_newfunc, \ sizeof(struct hashtype##_entry)); \ } \ \ void hashtype_free(struct hashtype *table) \ { \ bfd_hash_table_free(&table->root); \ } \ \ typeof(elt_t) *hashtype_lookup(struct hashtype *table, \ const char *string, \ bfd_boolean create) \ { \ struct bfd_hash_entry *e = \ bfd_hash_lookup(&table->root, string, create, \ TRUE); \ if (create) \ assert(e != NULL); \ else if (e == NULL) \ return NULL; \ return &container_of(e, struct hashtype##_entry, \ root)->val; \ } \ \ struct eat_trailing_semicolon #define DEFINE_HASH_TYPE(elt_t, hashtype, \ hashtype_init, hashtype_free, \ hashtype_lookup, \ elt_construct) \ DECLARE_HASH_TYPE(elt_t, hashtype, hashtype_init, \ hashtype_free, hashtype_lookup); \ IMPLEMENT_HASH_TYPE(elt_t, hashtype, hashtype_init, \ hashtype_free, hashtype_lookup, \ elt_construct); #ifndef bfd_get_section_size #define bfd_get_section_size(x) ((x)->_cooked_size) #endif DECLARE_HASH_TYPE(arelent *, arelentp_hash, arelentp_hash_init, arelentp_hash_free, arelentp_hash_lookup); DECLARE_HASH_TYPE(asymbol **, asymbolpp_hash, asymbolpp_hash_init, asymbolpp_hash_free, asymbolpp_hash_lookup); DECLARE_HASH_TYPE(const char *, string_hash, string_hash_init, string_hash_free, string_hash_lookup); struct label_map { asymbol *csym; const char *orig_label; const char *label; int count; }; DECLARE_VEC_TYPE(struct label_map, label_map_vec); DECLARE_HASH_TYPE(struct label_map *, label_mapp_hash, label_mapp_hash_init, label_mapp_hash_free, label_mapp_hash_lookup); struct entry_point { const char *label; const char *name; long offset; asymbol *symbol; }; DECLARE_VEC_TYPE(struct entry_point, entry_point_vec); struct span { struct supersect *ss; asymbol *symbol; const char *orig_label; const char *label; bfd_vma start; bfd_vma size; bfd_vma contents_size; bool keep; bool new; bool patch; bool bugpatch; bool datapatch; bool precallable; struct span *match; struct entry_point_vec entry_points; struct entry_point_vec pre_entry_points; bfd_size_type shift; }; DECLARE_VEC_TYPE(struct span, span_vec); struct superbfd { bfd *abfd; struct asymbolp_vec syms; struct supersect *new_supersects; struct label_map_vec maps; struct label_mapp_hash maps_hash; struct asymbolpp_vec new_syms; struct asymbolpp_hash csyms; struct string_hash callers; }; enum supersect_type { SS_TYPE_TEXT, SS_TYPE_DATA, SS_TYPE_RODATA, SS_TYPE_STRING, SS_TYPE_SPECIAL, SS_TYPE_IGNORED, SS_TYPE_KSPLICE, SS_TYPE_EXPORT, SS_TYPE_EXIT, SS_TYPE_KSPLICE_CALL, SS_TYPE_KSPLICE_EXTRACT, SS_TYPE_BUGTABLE, SS_TYPE_UNKNOWN }; struct supersect { struct superbfd *parent; const char *name; flagword flags; struct void_vec contents; int alignment; unsigned int entsize; struct arelentp_vec relocs; struct arelentp_vec new_relocs; struct supersect *next; struct asymbolp_vec syms; struct span_vec spans; struct arelentp_hash reloc_hash; asymbol *symbol; bool keep; enum supersect_type type; enum supersect_type orig_type; bool match_data_early; }; struct superbfd *fetch_superbfd(bfd *abfd); struct supersect *fetch_supersect(struct superbfd *sbfd, asection *sect); struct supersect *new_supersect(struct superbfd *sbfd, const char *name); void supersect_move(struct supersect *dest_ss, struct supersect *src_ss); #define sect_grow(ss, n, type) \ ((type *)sect_do_grow(ss, n, sizeof(type), __alignof__(type))) void *sect_do_grow(struct supersect *ss, size_t n, size_t size, int alignment); #define sect_copy(dest_ss, dest, src_ss, src, n) \ sect_do_copy(dest_ss, dest, src_ss, src, (n) * sizeof(*(src))) void sect_do_copy(struct supersect *dest_ss, void *dest, struct supersect *src_ss, const void *src, size_t n); #define strstarts(str, prefix) \ (strncmp(str, prefix, strlen(prefix)) == 0) #define ends_with(str, suffix) \ (strlen(str) >= strlen(suffix) && \ strcmp(&str[strlen(str) - strlen(suffix)], suffix) == 0) bfd_vma addr_offset(struct supersect *ss, const void *addr); bfd_vma reloc_offset(struct supersect *ss, arelent *reloc); arelent *find_reloc(struct supersect *ss, const void *addr); bfd_vma read_reloc(struct supersect *ss, const void *addr, size_t size, asymbol **symp); const void *read_pointer(struct supersect *ss, void *const *addr, struct supersect **ssp); const char *read_string(struct supersect *ss, const char *const *addr); #define read_num(ss, addr) ((typeof(*(addr))) \ read_reloc(ss, addr, sizeof(*(addr)), NULL)) static inline char *vstrprintf(const char *fmt, va_list ap) { char *str; assert(vasprintf(&str, fmt, ap) >= 0); return str; } static inline char * __attribute__((format (printf, 1, 2))) strprintf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); char *str = vstrprintf(fmt, ap); va_end(ap); return str; } ksplice-0.9.9/Ksplice.pm.in0000644000000000000000000001741511244274432014231 0ustar rootrootpackage Ksplice; use Cwd qw(abs_path getcwd); use Getopt::Long qw(:config bundling); use File::Basename; use File::Copy; use File::Path; use File::Spec::Functions qw(tmpdir); use File::Temp qw(tempfile tempdir); use Fatal qw(:void copy rename move chdir mkdir rmdir unlink rmtree); use IPC::Open2; use IPC::Open3; use Pod::Usage; use Text::ParseWords; use strict; use warnings; use Verbose qw(:2 copy rename move utime chdir mkdir mkpath unlink rmtree tempfile tempdir); require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw( Verbose GetOptions pod2usage shellwords $datadir $libexecdir @common_options $help $raw_errors child_error runval runval_raw runstr runstr_err runval_in runval_infile runval_outfile unpack_update get_stage set_stage set_debug_level set_partial get_abort_cause get_patch update_loaded get_debug_output get_conflicts get_raw_conflicts get_short_description read_file write_file abs_path getcwd basename dirname tmpdir copy rename move utime chdir mkdir mkpath unlink rmtree tempfile tempdir print_abort_error print_abort_code ); our ($datadir, $libexecdir) = qw(KSPLICE_DATA_DIR KSPLICE_LIBEXEC_DIR); our $help = 0; our $raw_errors = 0; our $printed_abort_code; our @common_options = ( "help|?" => \$help, "raw-errors" => \$raw_errors, "version" => sub { print "Ksplice version PACKAGE_VERSION\n"; exit(0); }, "api-version" => sub { print "KSPLICE_API_VERSION\n"; exit(0); }, "verbose|v:+" => \$Verbose::level, "quiet|q:+" => sub { $Verbose::level -= $_[1]; }, ); $SIG{__DIE__} = sub { die @_ if $^S || !$raw_errors; my ($msg) = @_; if(!$printed_abort_code) { print STDERR "OTHER\n$msg"; } exit(-1); }; sub child_error { if($raw_errors) { return ($? != 0); } if($? == -1) { print STDERR "Failed to exec child\n"; } elsif(($? & 127) != 0) { print STDERR "Child exited with signal ", ($? & 127), ($? & 128) ? " (core dumped)\n" : "\n"; } elsif($? >> 8 != 0) { print STDERR "Child exited with status ", $? >> 8, "\n"; } else { return 0; } return 1; } sub runval { my (@cmd) = @_; if(runval_raw(@cmd) != 0) { child_error(); die "Failed during: @cmd\n"; } } sub runval_raw { my (@cmd) = @_; my ($out, $err); print "+ @cmd\n" if($Verbose::level >= 1); if($raw_errors) { my $pid = open3(fileno STDIN, ">&STDOUT", ">/dev/null", @cmd); waitpid($pid, 0); return $?; } else { return system(@cmd); } } sub runstr { my @cmd = @_; print "+ @cmd\n" if($Verbose::level >= 1); local $/; local (*PIPE); if($raw_errors) { open3(fileno STDIN, \*PIPE, ">/dev/null", @cmd); } else { open PIPE, '-|', @cmd or die "Can't run @cmd: $!"; } my $output = ; close PIPE or $! == 0 or die "Can't run @cmd: $!"; return $output; } sub runstr_err { my @cmd = @_; print "+ @cmd\n" if($Verbose::level >= 1); local (*ERROR); my $pid = open3(fileno STDIN, '>&STDOUT', \*ERROR, @cmd); local $/; my $error = ; waitpid($pid, 0); print STDERR $error unless $raw_errors; return $error; } sub runval_in { my ($in, @cmd) = @_; print "+ @cmd <<'EOF'\n${in}EOF\n" if($Verbose::level >= 1); local (*WRITE); if($raw_errors) { open3(\*WRITE, ">&STDOUT", ">/dev/null", @cmd); } else { open(WRITE, '|-', @cmd) or die "Can't run @cmd: $!"; } print WRITE $in; close(WRITE) or $! == 0 or die "Can't run @cmd: $!"; if(child_error()) { die "Failed during: @cmd"; } } sub runval_infile { my ($infile, @cmd) = @_; print "+ @cmd < $infile\n" if($Verbose::level >= 1); local (*INFILE); open(INFILE, '<', $infile) or die "Can't open $infile: $!"; my $pid; if($raw_errors) { $pid = open3('<&INFILE', '>&STDOUT', ">/dev/null", @cmd); } else { $pid = open2('>&STDOUT', '<&INFILE', @cmd); } waitpid($pid, 0); if(child_error()) { die "Failed during: @cmd"; } } sub runval_outfile { my ($outfile, @cmd) = @_; print "+ @cmd > $outfile\n" if($Verbose::level >= 1); local (*OUTFILE); open(OUTFILE, '>', $outfile) or die "Can't open $outfile: $!"; my $pid; if($raw_errors) { $pid = open3('&OUTFILE', ">/dev/null", @cmd); } else { $pid = open2('>&OUTFILE', ' 1, CLEANUP => 1); runval("tar", "-C", $tmpdir, "--force-local", "-zxf", $file); my ($ksplice) = glob("$tmpdir/*/"); chop($ksplice); # remove the trailing slash return $ksplice; } sub get_sysfs { my ($kid) = @_; if(! -d "/sys/module") { die "/sys not mounted?\n"; } my $update = "ksplice_$kid"; if (-d "/sys/kernel/ksplice/$kid") { return "/sys/kernel/ksplice/$kid"; } if (-d "/sys/module/$update/ksplice") { return "/sys/module/$update/ksplice"; } return undef; } sub update_loaded { my ($kid) = @_; return defined(get_sysfs($kid)); } sub read_file { my ($file) = @_; local (*INPUT, $/); open(INPUT, "<", $file) or die $!; return ; } sub write_file { my ($file, $string) = @_; local *INPUT; open(INPUT, ">", $file) or die $!; print INPUT $string; } sub read_sysfs { my ($kid, $attr) = @_; my $sysfs = get_sysfs($kid); return undef if (!defined($sysfs)); return read_file("$sysfs/$attr"); } sub write_sysfs { my ($kid, $attr, $string) = @_; my $sysfs = get_sysfs($kid); return undef if (!defined($sysfs)); write_file("$sysfs/$attr", $string); } sub get_debug_output { my ($kid, $debugfs_out) = @_; my $update = "ksplice_$kid"; if (!$debugfs_out) { (undef, $debugfs_out) = tempfile('ksplice-debug-XXXXXX', DIR => tmpdir()); } if (runval_raw("grep", "-qFx", "nodev\tdebugfs", "/proc/filesystems") == 0) { my $debugfsdir = tempdir('ksplice-debugfs-XXXXXX', TMPDIR => 1); runval(qw(mount -t debugfs debugfs), $debugfsdir); if (-e "$debugfsdir/$update") { copy("$debugfsdir/$update", $debugfs_out); } runval(qw(umount), $debugfsdir); rmdir($debugfsdir); return $debugfs_out; } elsif ($? >> 8 == 1) { return (); } else { child_error(); exit(-1); } } sub get_stage { my ($kid) = @_; chomp(my $result = read_sysfs($kid, "stage")); return $result; } sub get_abort_cause { my ($kid) = @_; chomp(my $result = read_sysfs($kid, "abort_cause")); return $result; } sub get_conflicts { my ($kid) = @_; chomp(my $conflicts = read_sysfs($kid, "conflicts")); my @conflicts = split('\n', $conflicts); my $out = ''; foreach my $conflict (@conflicts) { my ($name, $pid, @symbols) = split(' ', $conflict); next if (!@symbols); $out .= "Process $name(pid $pid) is using the following symbols changed by update $kid:\n"; foreach my $symbol (@symbols) { $out .= " $symbol\n"; } } return $out; } sub get_raw_conflicts { my ($kid) = @_; my $conflicts = read_sysfs($kid, "conflicts"); return $conflicts; } sub get_patch { my ($kid) = @_; my $result = read_file("/var/run/ksplice/updates/$kid/patch"); return $result; } sub get_short_description { my ($kid) = @_; open(INPUT, "<", "/var/run/ksplice/updates/$kid/description") or return undef; my $result = ; close(INPUT); return $result; } sub set_stage { my ($kid, $string) = @_; write_sysfs($kid, "stage", "$string\n"); } sub set_debug_level { my ($kid, $string) = @_; write_sysfs($kid, "debug", "$string\n"); } sub set_partial { my ($kid, $string) = @_; write_sysfs($kid, "partial", "$string\n"); } sub print_abort_error { my ($kid, %errors) = @_; my $error = get_abort_cause($kid); print_abort_code($error, %errors); if ($error eq 'code_busy') { if($raw_errors) { print STDERR get_raw_conflicts($kid); } else { print STDERR get_conflicts($kid); } } $printed_abort_code = 1; } sub print_abort_code { my ($error, %errors) = @_; if($raw_errors) { print STDERR "$error\n"; } else { $error = "UNKNOWN" if (!exists $errors{$error}); print STDERR "\n$errors{$error}\n"; } $printed_abort_code = 1; } END { $Verbose::level = 0; chdir("/"); } 1; ksplice-0.9.9/ksplice-create.in0000644000000000000000000004525611244274432015123 0ustar rootroot#!/usr/bin/perl # Copyright (C) 2007-2009 Ksplice, Inc. # Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA # 02110-1301, USA. use strict; use warnings; use lib 'KSPLICE_DATA_DIR'; use Ksplice; my ($patchfile, $diffext, $git, $orig_config_dir, $jobs, $kid); my $description; my $series = 0; my $build_modules = 0; my $ksplice_short_name_hack = 0; my @only_targets; my @extra_match; my @exclude_match; my $standalone; my ($prebuild, $skip_prebuild) = (0, 0); my @patch_opt = "-p1"; GetOptions(@common_options, "id=s" => \$kid, "patch=s" => \$patchfile, "description=s" => \$description, "diffext=s" => \$diffext, "git=s" => \$git, "prebuild" => \$prebuild, "series!" => \$series, "build-modules!" => \$build_modules, "only-targets=s" => \@only_targets, "extra-match=s" => \@extra_match, "exclude-match=s" => \@exclude_match, "standalone!" => \$standalone, "short-name-hack!" => \$ksplice_short_name_hack, "skip-prebuild" => \$skip_prebuild, "jobs|j:i" => \$jobs, "config=s" => \$orig_config_dir, "patch-opt=s" => \@patch_opt) or pod2usage(1); pod2usage(1) if($help || scalar(@ARGV) != 1); my $actions = (defined $patchfile) + (defined $diffext) + (defined $git) + $prebuild; pod2usage(1) if($actions != 1); my $have_Git = eval { require Git }; $have_Git or die $@ if defined $git; my ($linuxtree) = (abs_path($ARGV[0])); if(!defined $orig_config_dir) { $orig_config_dir = "$linuxtree/ksplice"; } else { $orig_config_dir = abs_path($orig_config_dir); if($orig_config_dir =~ $linuxtree) { die "Aborting: User-specified ORIG_CONFIG cannot be KERNEL_SOURCE or a subdirectory"; } } if(!defined $orig_config_dir || ! -d $orig_config_dir) { die "Failed to find ORIG_CONFIG directory ($orig_config_dir)"; } if(! -e "$orig_config_dir/System.map") { die "Failed to find System.map file in ORIG_CONFIG directory"; } my $kernel_headers_dir = "$orig_config_dir/build"; $kernel_headers_dir = $linuxtree unless(-d $kernel_headers_dir); my @kbuild_flags = (); if(-e "$orig_config_dir/flags") { open(FLAGS, '<', "$orig_config_dir/flags") or die; local $/; @kbuild_flags = shellwords(scalar ); close(FLAGS); } $ENV{KSPLICE_VERBOSE} = $Verbose::level; $ENV{KSPLICE_CONFIG_DIR} = $orig_config_dir; my @chars = ('a'..'z', 0..9); $kid = join '', map { $chars[int(rand(36))] } 0..7 if(!defined $kid); my $ksplice = "ksplice-$kid"; $ENV{KSPLICE_KID} = $kid; # Some versions of Fedora have System.map files whose symbol addresses disagree # with the running kernel by a constant address offset. Here, Ksplice notes the # System.map address for printk so that it can later compare this address against # the kernel's address for printk. This comparison helps Ksplice work around # this Fedora problem, and this comparison also helps Ksplice detect whether # the user has provided an incorrect System.map file. my $map_printk = runstr("$datadir/ksplice-obj.pl", "system_map_lookup", "printk"); print "Starting kernel builds (this process might take a long time)...\n" if($Verbose::level >= 0); $patchfile = abs_path($patchfile) if(defined $patchfile); my $origdir = getcwd(); chdir($linuxtree); my $git_rev; my $git_repo; if (defined $git) { $git_repo = Git->repository(); ($git_rev) = $git_repo->command(qw(rev-parse --verify), $git); } else { $git_repo = eval { Git->repository() }; } my @make = ("make", "-rR"); if(defined $jobs) { push @make, "-j$jobs"; } elsif(defined $ENV{CONCURRENCY_LEVEL}) { push @make, "-j$ENV{CONCURRENCY_LEVEL}"; } if($Verbose::level >= 2) { push @make, "V=1"; } elsif($Verbose::level < 0) { push @make, "-s"; } $ENV{PATH} = "$datadir:$ENV{PATH}"; my @make_ksplice = (@make, "-f", "$datadir/Makefile.ksplice", @kbuild_flags); push(@make_ksplice, "KSPLICE_BUILD_MODULES=1") if ($build_modules); if(-e "include/config/kernel.release") { push(@make_ksplice, "-o", "include/config/kernel.release"); } my @revert_flags = ("KSPLICE_MODE=revert"); push(@revert_flags, "KSPLICE_SERIES=y") if ($series); sub git_have_ksplice_pre { return $git_repo->command(qw(for-each-ref refs/ksplice/pre)) ne ''; } if(-e "$orig_config_dir/.config" && !-e "$linuxtree/.config") { copy("$orig_config_dir/.config", "$linuxtree/.config"); utime((stat("$orig_config_dir/.config"))[8, 9], "$linuxtree/.config"); } sub revert_orig() { for(split(/\0/, runstr(qw(find -name *.KSPLICE_presrc -print0)))) { my ($file) = m/^(.*)\.KSPLICE_presrc$/; if ($series) { unlink($_); } else { rename($_, $file); } } if (defined $git_repo && git_have_ksplice_pre) { if ($series) { $git_repo->command_noisy(qw(update-ref -m), "ksplice-create: freeze", qw(refs/ksplice/pre HEAD refs/ksplice/pre)); } else { $git_repo->command_noisy(qw(update-index --refresh)); $git_repo->command_noisy(qw(read-tree -m --trivial -u refs/ksplice/pre)); $git_repo->command_noisy(qw(update-ref -m), "ksplice-create: revert", qw(HEAD refs/ksplice/pre HEAD)); } } runval(@make_ksplice, @revert_flags); } revert_orig(); if (defined $git_repo && !git_have_ksplice_pre) { $git_repo->command_noisy(qw(update-ref -m), "ksplice-create: snap", qw(refs/ksplice/pre HEAD), ''); } if(!$skip_prebuild) { if(-e "$orig_config_dir/.config") { copy("$orig_config_dir/.config", "$linuxtree/.config"); utime((stat("$orig_config_dir/.config"))[8, 9], "$linuxtree/.config"); } my @snap_flags = ("KSPLICE_MODE=snap"); runval_raw(@make_ksplice, @snap_flags) == 0 or die "Aborting: Prebuild failed"; sleep(1); } exit(0) if($prebuild); my $tmpdir = tempdir('ksplice-tmp-XXXXXX', TMPDIR => 1, CLEANUP => 1); copy($patchfile, "$tmpdir/patch") if(defined $patchfile); $patchfile = "$tmpdir/patch"; if(defined $diffext) { open(PATCH, '>', $patchfile) or die; for(split(/\0/, runstr("find", "-name", "*$diffext", "-print0"))) { my ($file) = /^(.*)\Q$diffext\E/ or die; print PATCH runstr("diff", "-u", "--", $file, $_); } close(PATCH) or die; @patch_opt = ("-p0"); } my $kmodsrc = "$tmpdir/kmodsrc"; runval("cp", "-a", "--", "$datadir/kmodsrc", $kmodsrc); $ENV{KSPLICE_KMODSRC} = $kmodsrc; my @make_kmodsrc = (@make, "-C", $kernel_headers_dir, "M=$kmodsrc", "KSPLICE_KID=$kid", "KSPLICE_VERSION=PACKAGE_VERSION", "map_printk=$map_printk"); if (!defined($standalone)) { $standalone = (!-e "$linuxtree/.config" || runval_raw(qw(grep -q ^CONFIG_KSPLICE=[ym]$), "$linuxtree/.config") != 0); } push(@make_kmodsrc, "KSPLICE_STANDALONE=1") if ($standalone); push(@make_kmodsrc, "KSPLICE_SHORT_NAME_HACK=1") if ($ksplice_short_name_hack); my @make_kmodsrc_install = (@make_kmodsrc, qw(modules_install --old-file=_modinst_post --old-file=_emodinst_post), "MAKE=make --old-file=_modinst_post --old-file=_emodinst_post", "INSTALL_MOD_STRIP=1", "MODLIB=$tmpdir/ksplice-modules"); runval(@make_kmodsrc); runval(@make_kmodsrc_install); @patch_opt = ("-s", @patch_opt) if ($Verbose::level < 0); if (defined $git) { $git_repo->command_noisy(qw(update-index --refresh)); $git_repo->command_noisy(qw(read-tree -m --trivial -u), $git_rev); $git_repo->command_noisy(qw(update-ref -m), "ksplice-create: diff", "HEAD", $git_rev); open(PATCH, '>', $patchfile) or die; if ($git_repo->command(qw(rev-parse --verify HEAD^)) eq $git_repo->command(qw(rev-parse --verify refs/ksplice/pre))) { print PATCH scalar($git_repo->command(qw(log -1 HEAD --))), "\n"; } print PATCH scalar($git_repo->command(qw(diff-tree -p refs/ksplice/pre HEAD --))); close(PATCH) or die; } else { runval_infile($patchfile, "patch", @patch_opt, "-bz", ".KSPLICE_presrc"); } my @diff_flags = ("KSPLICE_MODE=diff"); push @diff_flags, "KSPLICE_EXTRA_MATCH=@extra_match" if (@extra_match); push @diff_flags, "KSPLICE_EXCLUDE_MATCH=@exclude_match" if (@exclude_match); push @diff_flags, "KSPLICE_ONLY_TARGETS=@only_targets" if (@only_targets); if(runval_raw(@make_ksplice, @diff_flags) != 0) { revert_orig() if(defined($diffext)); die "Aborting: Applying the patch appears to break the kernel build"; } sub copy_debug { my ($file) = @_; my ($dir, $base) = (dirname($file), basename($file)); -d "$tmpdir/objects/$dir" or mkpath("$tmpdir/objects/$dir"); copy($file, "$tmpdir/objects/$file"); my $cmdfile = "$dir/.$base.cmd"; copy($cmdfile, "$tmpdir/objects/$cmdfile") if(-e $cmdfile); } mkdir("$tmpdir/objects"); for (split(/\0/, runstr(qw(find -name *.KSPLICE* ! ( -name *.KSPLICE -empty ) ! -name .*.KSPLICE.cmd -print0)))) { next if (basename($_) =~ m/^(?:vmlinux|vmlinux\.o|\.tmp_vmlinux[0-9]+|\.tmp_kallsyms[0-9]+\.o|built-in\.o)\.KSPLICE_pre$/); copy_debug($_); copy_debug($1) if (m/^(.*)\.KSPLICE_pre(?:src)?$/); } my @modulepaths = (); my @modules = (); foreach(glob("$kmodsrc/*.mod.KSPLICE")) { open MOD, '<', $_; chomp(my $mod = ); close MOD; push @modulepaths, "$mod.ko" if (basename($mod) ne "vmlinux"); push @modules, basename($mod); } if(!@modules) { revert_orig() if(defined($diffext)); print STDERR "No changes detected.\n"; exit(66); } if ($build_modules) { mkdir("$tmpdir/modules"); runval(@make_ksplice, "KSPLICE_MODE=modinst", "MODLIB=$tmpdir/modules", "INSTALL_MOD_STRIP=1", "modules=@modulepaths"); } revert_orig() if(defined($diffext)); runval(@make_kmodsrc, "KSPLICE_MODULES=@modules", "KSPLICE_SKIP_CORE=1"); runval(@make_kmodsrc_install, "KSPLICE_MODULES=@modules", "KSPLICE_SKIP_CORE=1"); chdir($tmpdir); mkdir($ksplice); move($patchfile, $ksplice); if ($description) { write_file("$ksplice/description", "$description\n"); } write_file("$ksplice/api-version", "KSPLICE_API_VERSION\n"); write_file("$ksplice/timestamp", time() . "\n"); runval_outfile("$ksplice/utsname", "$libexecdir/ksplice-kernel-utsname", "$kmodsrc/offsets.o"); mkdir("inspect"); open(CONTENTS, ">", "$ksplice/contents"); foreach my $mod (@modules) { (my $target = $mod) =~ s/-/_/g; my $mid = "${kid}_$target"; my $module = "ksplice-$mid"; my ($new, $old); unless($ksplice_short_name_hack) { $new = "new"; $old = "old"; } else { $new = "n"; $old = "o"; } rename("$tmpdir/ksplice-modules/extra/$module-$new.ko", "$ksplice/$module-$new.ko"); runval_outfile("inspect/$module-$new", "$libexecdir/ksplice-inspect", "$ksplice/$module-$new.ko"); rename("$tmpdir/ksplice-modules/extra/$module-$old.ko", "$ksplice/$module-$old.ko"); runval_outfile("inspect/$module-$old", "$libexecdir/ksplice-inspect", "$ksplice/$module-$old.ko"); print CONTENTS "change $target ksplice_${mid}_$new $module-$new.ko", " ksplice_${mid}_$old $module-$old.ko\n"; } if ($standalone) { rename("$tmpdir/ksplice-modules/extra/ksplice-$kid.ko", "$ksplice/ksplice-$kid.ko"); print CONTENTS "core ksplice_$kid ksplice-$kid.ko\n"; } if ($build_modules) { foreach my $mod (@modulepaths) { (my $target = basename($mod)) =~ s/-/_/g; print CONTENTS "module $target $mod\n"; } } mkdir("$ksplice/debug"); rename("objects", "$ksplice/debug/objects"); rename("inspect", "$ksplice/debug/inspect"); rename("modules", "$ksplice/modules") if ($build_modules); rename("$kmodsrc", "$ksplice/debug/kmodsrc"); close(CONTENTS); runval("tar", "czf", "$ksplice.tar.gz", "--", $ksplice); copy("$ksplice.tar.gz", "$origdir/$ksplice.tar.gz"); print "Ksplice update tarball written to $ksplice.tar.gz\n"; exit(0); =head1 NAME ksplice-create - Create a set of kernel modules for a rebootless kernel update =head1 SYNOPSIS B [I] B<--patch=>I I B [I] B<--diffext=>I I B [I] B<--git=>I I B [I] B<--prebuild> I =head1 DESCRIPTION B creates a set of Ksplice kernel modules that, when loaded, will apply a user-specified source code patch to the running binary kernel. Before you use B on a patch, you should confirm that the desired source code change does not make any semantic changes to kernel data structures--that is, changes that would require existing instances of kernel data structures to be transformed (e.g., a patch that adds a field to a global data structure would require the existing data structures to change). If you use Ksplice on a patch that changes data structure semantics, Ksplice will not detect the problem and you could experience kernel problems as a result. The to-be-applied source code patch can be specified by providing a L file (B<--patch=>I) or by providing a file extension (B<--diffext=>I). If a file extension is specified, then the desired source code patch will be determined by comparing all of the files in the I directory tree whose names end with the extra extension I against the corresponding files without the extra extension. Only the new files containing the extra extension in their filenames should be modified. Here is an example of using a file extension to specify a patch: $ cp KERNEL_SOURCE/kernel/sys.c KERNEL_SOURCE/kernel/sys.c.prctl_fixed [edit sys.c.prctl_fixed to include the desired changes] $ ksplice-create --diffext=.prctl_fixed KERNEL_SOURCE KERNEL_SOURCE must be a directory containing the to-be-updated kernel's original source code. If your Linux distribution applies patches to the Linux kernel during the kernel build process, then those patches must be applied to the I directory before invoking B on that directory. B will not modify the source code in the I directory tree, but it will perform a kernel build in that directory tree. I can be used to specify the directory containing the to-be-updated kernel's original F<.config> file and original F file (the files should have exactly those names). I defaults to IB. The default L compiler and L assembler on the system should be as close to the compiler and assembler originally used to build the running kernel as possible. If the current compiler and linker are too different from the original compiler and linker, B will abort when applying the update. B outputs a L file, compressed with L, containing the desired Ksplice update modules. This tarball will be created in the current directory, and it can be manipulated using the other Ksplice utilities, such as B. The first time that B is invoked on a I directory, it must build that kernel from scratch, which is much slower than the rest of the update-creation process. B<--prebuild> can be used to perform this initial kernel build without providing a source code patch. In order to patch a function that has previously been patched by Ksplice, the user needs to ensure that the I directory provided to Ksplice contains the source for the currently running kernel, including any patches that have previously been applied by Ksplice. =head1 OPTIONS =over 8 =item B<--patch=>I Builds a Ksplice update out of the given L file I. =item B<--diffext=>I Builds a Ksplice update using the modified source files with names ending in I. The patch will be determined by comparing all of the files in the I directory tree whose names end with the extra extension I against the corresponding files without the extra extension. =item B<--git>=I Builds a Ksplice update using the commit I in the Git working tree I. The original state corresponding to the running kernel is remembered in the Git ref B, which will be created from the current B if it does not yet exist (and can be changed using the B<--series> option). Therefore, the source code change to be applied corresponds to the output of B I. =item B<--prebuild> Compiles the original source code that will be needed to build future Ksplice updates. If any Ksplice updates have previously been built in the I tree, the source files in the tree are reverted to their original state. =item B<--series> Specifies that the current state of the I tree should be used as the original source that corresponds to the running kernel. If a Ksplice update has recently been built in the I tree, this option specifies that the Ksplice update being built should be applied after the previous update in series. This option can be used with B<--prebuild> to forget the previous original state and perform no other action. =item B<--build-modules> For a patch that includes changes to kernel modules, in addition to building a hot update that can be applied to the running kernel, this option will cause B to generate a set of new modules based on the updated source code. These modules can be used to replace the kernel modules stored on disk, where they can later be loaded normally after part of the hot update has been applied using L B<--partial>. =item B<-v>, B<--verbose> Causes B to print debugging messages about its progress. Using multiple -v options increases the verbosity. The maximum is 2. =item B<-j> I, B<--jobs=>I Specifies the number of jobs to run simultaneously while performing kernel builds. B also honors the environment variable CONCURRENCY_LEVEL. =item B<--patch-opt=>I Can be used to pass options to L. If this option is NOT specified, then B<-p1> is passed to B. If this option is specified, then only the specified options will be passed to B. This option can be repeated in order to pass multiple options to B. This option is ignored when the to-be-applied source code patch is specified using B<--diffext>. =item B<--id=>I Specifies the unique value that will be used as the identifier of the Ksplice update. This identifier will, for example, appear in the name of the update tarball. By default, a random 8-character ID will be generated. =back =head1 SEE ALSO L, L, L =head1 BUGS Please report bugs to . =head1 AUTHORS Jeff Arnold, Anders Kaseorg, and Tim Abbott =head1 COPYRIGHT Copyright (C) 2007-2009 Ksplice, Inc. This is free software and documentation. You can redistribute and/or modify it under the terms of the GNU General Public License, version 2. =cut ksplice-0.9.9/kernel-utsname.c0000644000000000000000000000304311244274432014762 0ustar rootroot/* Copyright (C) 2008-2009 Ksplice, Inc. * Authors: Tim Abbott, Anders Kaseorg, Jeff Arnold * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA * 02110-1301, USA. */ #define _GNU_SOURCE #include "objcommon.h" #include static void print_section(struct superbfd *sbfd, const char *fieldname, const char *sectname) { asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname); assert(sect != NULL); struct supersect *ss = fetch_supersect(sbfd, sect); printf("%s: %s\n", fieldname, read_string(ss, ss->contents.data)); } int main(int argc, char *argv[]) { bfd *ibfd; assert(argc >= 1); bfd_init(); ibfd = bfd_openr(argv[1], NULL); assert(ibfd); char **matching; assert(bfd_check_format_matches(ibfd, bfd_object, &matching)); struct superbfd *sbfd = fetch_superbfd(ibfd); print_section(sbfd, "Sysname", ".uts_sysname"); print_section(sbfd, "Machine", ".uts_machine"); print_section(sbfd, "Release", ".uts_release"); print_section(sbfd, "Version", ".uts_version"); return 0; } ksplice-0.9.9/Makefile.in0000644000000000000000000001000211244274432013722 0ustar rootrootsrcdir = @srcdir@ VPATH = $(srcdir) prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ libexecdir = @libexecdir@ mandir = @mandir@ datadir = @datadir@ datarootdir = @datarootdir@ CC = @CC@ CFLAGS = @CFLAGS@ CPPFLAGS = @CPPFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ PACKAGE_VERSION = @PACKAGE_VERSION@ KSPLICE_API_VERSION = @KSPLICE_API_VERSION@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ perl_primary = ksplice-create ksplice-view ksplice-apply ksplice-undo Ksplice.pm ksplice-obj.pl perl_man = $(patsubst %,%.8,$(perl_primary)) objutils = objmanip inspect kernel-utsname itab = kmodsrc/x86/libudis86/itab.h kmodsrc/x86/libudis86/itab.c have_static := $(wildcard $(srcdir)/objmanip-static) default: $(perl_primary) $(perl_man) objutils $(itab) @echo "Ready for 'make install'" ifeq ($(strip $(have_static)),) objutils: $(objutils) $(addprefix install-,$(objutils)): install-%: % install -m755 -D $< $(DESTDIR)$(libexecdir)/ksplice-$* else objutils: $(addprefix install-,$(objutils)): install-%: %-static install -m755 -D $< $(DESTDIR)$(libexecdir)/ksplice-$* endif $(perl_primary): %: %.in Makefile sed 's|PACKAGE_VERSION|$(PACKAGE_VERSION)|;s|KSPLICE_API_VERSION|$(KSPLICE_API_VERSION)|;s|PACKAGE_BUGREPORT|$(PACKAGE_BUGREPORT)|;s|KSPLICE_DATA_DIR|$(datadir)/ksplice|;s|KSPLICE_LIBEXEC_DIR|$(libexecdir)|' $< > $@ $(perl_man): %.8: % pod2man --center="Ksplice" --release="Ksplice v$(PACKAGE_VERSION)" --section=8 $< $@ $(objutils): %: %.c objcommon.c objcommon.h kmodsrc/ksplice.h $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $< $(srcdir)/objcommon.c $(LIBS) -o $@ kmodsrcfiles = \ kmodsrc/ksplice.c \ kmodsrc/ksplice.h \ kmodsrc/x86/ksplice-arch.c \ kmodsrc/arm/ksplice-arch.c \ kmodsrc/old_code_loader.c \ kmodsrc/new_code_loader.c \ kmodsrc/Makefile \ kmodsrc/ksplice.lds.S \ kmodsrc/ksplice-rmsyms.lds \ kmodsrc/offsets.c \ kmodsrc/offsets.h \ kmodsrc/x86/udis86.h \ kmodsrc/x86/libudis86/decode.c \ kmodsrc/x86/libudis86/itab.c \ kmodsrc/x86/libudis86/syn-att.c \ kmodsrc/x86/libudis86/syn-intel.c \ kmodsrc/x86/libudis86/input.c \ kmodsrc/x86/libudis86/syn.c \ kmodsrc/x86/libudis86/udis86.c \ kmodsrc/x86/libudis86/decode.h \ kmodsrc/x86/libudis86/input.h \ kmodsrc/x86/libudis86/syn.h \ kmodsrc/x86/libudis86/extern.h \ kmodsrc/x86/libudis86/itab.h \ kmodsrc/x86/libudis86/types.h $(itab): kmodsrc/x86/libudis86/x86optable.xml kmodsrc/x86/libudis86/opgen.py cd kmodsrc/x86/libudis86 && python opgen.py x86optable.xml $(addprefix install-,$(kmodsrcfiles)): install-%: % install -m644 -D $< $(DESTDIR)$(datadir)/ksplice/$< install: default $(addprefix install-,$(objutils)) $(addprefix install-,$(kmodsrcfiles)) install -m644 -D ksplice-create.8 $(DESTDIR)$(mandir)/man8/ksplice-create.8 install -m644 -D ksplice-apply.8 $(DESTDIR)$(mandir)/man8/ksplice-apply.8 install -m644 -D ksplice-undo.8 $(DESTDIR)$(mandir)/man8/ksplice-undo.8 install -m644 -D ksplice-view.8 $(DESTDIR)$(mandir)/man8/ksplice-view.8 install -m755 -D ksplice-create $(DESTDIR)$(bindir)/ksplice-create install -m755 -D ksplice-view $(DESTDIR)$(sbindir)/ksplice-view install -m755 -D ksplice-apply $(DESTDIR)$(sbindir)/ksplice-apply install -m755 -D ksplice-undo $(DESTDIR)$(sbindir)/ksplice-undo install -m755 -D $(srcdir)/ksplice-cc.pl $(DESTDIR)$(datadir)/ksplice/ksplice-cc.pl install -m755 -D $(srcdir)/ksplice-obj.pl $(DESTDIR)$(datadir)/ksplice/ksplice-obj.pl install -m644 -D $(srcdir)/ksplice-patch/ksplice-patch.h $(DESTDIR)$(datadir)/ksplice/ksplice-patch/ksplice-patch.h install -m644 -D $(srcdir)/ksplice-patch/ksplice-shadow.h $(DESTDIR)$(datadir)/ksplice/ksplice-patch/ksplice-shadow.h install -m644 -D $(srcdir)/Makefile.ksplice $(DESTDIR)$(datadir)/ksplice/Makefile.ksplice install -m644 -D Ksplice.pm $(DESTDIR)$(datadir)/ksplice/Ksplice.pm install -m644 -D Verbose.pm $(DESTDIR)$(datadir)/ksplice/Verbose.pm clean: rm -f $(perl_primary) rm -f $(perl_man) rm -f $(objutils) distclean: clean rm -f Makefile kmodsrc/Makefile rm -f $(objutils:=-static) rm -f $(itab) rm -f configure config.status config.log ksplice-0.9.9/README0000644000000000000000000000104111244274432012540 0ustar rootrootKsplice Copyright (C) 2007-2009 Ksplice, Inc. Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2. For more information about Ksplice, please see . Installation instructions: $ ./configure $ make $ make install Notable Build Dependencies: - GNU binary file descriptor (BFD) library (version 2.15 or later) (available in Debian's binutils-dev package and in other distributions) ksplice-0.9.9/configure.ac0000644000000000000000000000614711244274432014162 0ustar rootrootAC_INIT([Ksplice], [0.9.9], [devel@ksplice.com]) AC_SUBST([KSPLICE_API_VERSION], [2]) AC_ARG_WITH([libbfd], [ --with-libbfd=FILE path to libbfd.a], [ac_libbfd=$withval], [ac_libbfd=NONE]) AC_ARG_WITH([libiberty], [ --with-libiberty=FILE path to libiberty.a], [ac_libiberty=$withval], [ac_libiberty=NONE]) AC_ARG_WITH([libz], [ --with-libz=FILE path to libz.a], [ac_libz=$withval], [ac_libz=NONE]) AC_ARG_WITH([bfd-include-dir], [ --with-bfd-include-dir=DIR path to directory containing bfd.h], [ac_bfd_include_dir=$withval], [ac_bfd_include_dir=NONE]) AC_PROG_CC if test "$ac_libz" = "NONE"; then AC_CHECK_LIB([z], [zlibVersion]) else LIBS="$ac_libz $LIBS" fi if test "$ac_libiberty" = "NONE"; then AC_CHECK_LIB([iberty], [objalloc_create]) else LIBS="$ac_libiberty $LIBS" fi if test "$ac_libbfd" = "NONE"; then ac_libbfd=auto AC_CHECK_LIB([bfd], [bfd_openr], , [ac_libbfd=NONE]) else LIBS="$ac_libbfd $LIBS" fi if test "$ac_bfd_include_dir" != "NONE"; then CPPFLAGS="$CPPFLAGS -I$ac_bfd_include_dir" fi AC_CHECK_HEADERS([bfd.h], , [BFD_H="no"]) AC_CHECK_MEMBER([struct bfd_hash_table.entsize], [CPPFLAGS="$CPPFLAGS -DBFD_HASH_TABLE_HAS_ENTSIZE"], [], [[#include ]]) if ! test -e "objmanip-static"; then if test "$ac_libbfd" = "NONE"; then echo echo "Ksplice could not locate libbfd.a and/or libiberty.a on your system." echo "You can obtain these libraries from the GNU binutils collection." echo "These libraries are available on many Linux distributions as a" echo "package called 'binutils-dev' or 'binutils-devel'." echo "If your distribution does not provide GNU binutils, you can install" echo "GNU binutils from source -- see http://www.gnu.org/software/binutils/." echo echo "If these libraries are already installed on your system, then you need" echo "to tell Ksplice where to find them by running configure again:" echo echo " ./configure --with-libbfd= --with-libiberty=" echo echo "Depending on the host system you may also need to provide zlib:" echo echo " ./configure ... --with-libz=" echo exit 1 fi if test "$BFD_H" = "no"; then echo echo "Ksplice could not locate bfd.h on your system." echo "If this header file is already installed on your system, then you need" echo "to tell Ksplice where to find it by running configure again:" echo echo " ./configure --with-bfd-include-dir=" echo exit 1 fi fi AC_PATH_PROG([PATCH], [patch]) AC_PATH_PROG([POD2MAN], [pod2man]) if test "$PATCH" = ""; then echo echo "Ksplice could not locate patch on your system." echo exit 1 fi if test "$POD2MAN" = ""; then echo echo "Ksplice could not locate pod2man on your system." echo exit 1 fi AC_PROG_PERL_MODULES([Cwd Getopt::Long File::Basename File::Copy File::Path File::Spec::Functions File::Temp Fatal IPC::Open2 IPC::Open3 Pod::Usage Text::ParseWords], , [AC_MSG_ERROR([Missing some required perl modules])]) AC_CONFIG_FILES([Makefile kmodsrc/Makefile]) AC_OUTPUT ksplice-0.9.9/ksplice-cc.pl0000755000000000000000000000241111244274432014237 0ustar rootroot#!/usr/bin/perl # Copyright (C) 2008-2009 Ksplice, Inc. # Authors: Anders Kaseorg, Jeff Arnold, Tim Abbott # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA # 02110-1301, USA. use strict; use warnings; use IPC::Open3; use Cwd qw(abs_path); use File::Basename; my $dir = abs_path(dirname($0) . "/ksplice-patch"); my @cmd; foreach (@ARGV) { if (/^-ksplice-cflags-api=1$/) { push @cmd, "-I$dir"; push @cmd, qw(-D__DATE__="<{DATE...}>" -D__TIME__="<{TIME}>"); } else { push @cmd, $_; } } my $pid = open3('<&STDIN', '>&STDOUT', \*ERROR, @cmd); while () { next if /^(?::\d+:\d+)?: warning: "(?:__DATE__|__TIME__)" redefined$/; print STDERR; } close ERROR; waitpid($pid, 0) == $pid and ($? & 127) == 0 or die; exit($? >> 8); ksplice-0.9.9/COPYING0000644000000000000000000004310311244274432012720 0ustar rootroot GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. ksplice-0.9.9/ksplice-apply.in0000644000000000000000000002410111244274432014767 0ustar rootroot#!/usr/bin/perl # Copyright (C) 2007-2009 Ksplice, Inc. # Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA # 02110-1301, USA. use strict; use warnings; use sigtrap 'handler', \&handler, qw(normal-signals error-signals); use lib 'KSPLICE_DATA_DIR'; use Ksplice; our %apply_errors; initialize_abort_code_table(); my $debug; my $debugon = 0; my $partial = 0; GetOptions(@common_options, "partial" => \$partial, "debug" => \$debugon, "debugfile=s" => \$debug) or pod2usage(1); pod2usage(1) if($help || scalar(@ARGV) != 1); my $file = $ARGV[0]; $debugon = 1 if(defined $debug); $debug = abs_path($debug) if (defined $debug); chdir(unpack_update($file)); die "No contents file in $file\n" if (!-e "contents"); open(CONTENTS, '<', "contents"); my $core; my @changes; my $kid; while () { my ($type, @args) = split(' ', $_); if ($type eq 'core') { die "Multiple core modules in $file!" if (defined $core); $core = {}; @$core{qw(module file)} = @args; } elsif ($type eq 'change') { my $change = {}; @$change{qw(target new_code new_code_file old_code old_code_file)} = @args; push @changes, $change; my ($ckid) = $change->{'new_code'} =~ m/^ksplice_([^-_]+)_/ or die "Bad new_code $change->{'new_code'}"; !$kid or $kid eq $ckid or die "Multiple kids"; $kid = $ckid; } } $kid or die "No kid"; close(CONTENTS); die "Update was built using an old version of Ksplice" if (@changes == 0); my $nounload = runstr("lsmod") =~ m/- $/m; my $update = "ksplice_$kid"; if(update_loaded($kid)) { my $stage = get_stage($kid); if ($stage eq "applied") { print STDERR "Ksplice update $kid already applied.\n" unless $raw_errors; exit(0); } die "Reversed Ksplice module $update already loaded!" if ($stage eq "reversed"); } runstr_err(qw(modprobe -q ksplice)) eq "" or die("Error loading Ksplice module.\n"); if (defined $core) { die "Could not find Ksplice core module $core->{file}\n" if (!-e $core->{file}); if (runstr("lsmod") =~ m/^\Q$core->{module}\E\s+/) { die "Ksplice core module $core already loaded."; } if (!load_module($core->{file}, "debug=$debugon")) { die "Error loading Ksplice core module $core->{module} for update $kid"; } } foreach my $change (@changes) { die unless (-e $change->{old_code_file} && -e $change->{new_code_file}); if ($change->{'target'} ne 'vmlinux' && runstr("lsmod") !~ m/^\Q$change->{target}\E\s+/m) { if (!$partial) { cleanup_modules(); print_abort_code("target_not_loaded", %apply_errors); die "Module $change->{target} to be patched not loaded"; } } } foreach my $change (@changes) { if(!load_module($change->{new_code_file})) { die "Error loading new code module $change->{new_code}"; } if(!load_module($change->{old_code_file})) { if($debugon) { my $debugfile = get_debug_output("init_$kid", $debug); print("Debugging output saved to $debugfile\n") if $debugfile; } cleanup_modules(); die("Error loading old code module $change->{old_code}\n"); } } mkpath("/var/run/ksplice/updates/$kid"); copy("patch", "/var/run/ksplice/updates/$kid/patch") if (-e "patch"); copy("description", "/var/run/ksplice/updates/$kid/description") if (-e "description"); set_debug_level($kid, $debugon); set_partial($kid, $partial); set_stage($kid, "applied"); my $stage = get_stage($kid); if($stage ne 'applied') { print STDERR "Error applying Ksplice update $kid:\n" unless $raw_errors; print_error($kid); if ($debugon) { my $debugfile = get_debug_output($kid, $debug); print("Debugging output saved to $debugfile\n") if $debugfile; } rmtree("/var/run/ksplice/updates/$kid") if (-e "/var/run/ksplice/updates/$kid"); cleanup_modules(); exit(-1); } if (!$nounload) { foreach my $change (@changes) { runval('rmmod', $change->{old_code}); runval('rmmod', $change->{new_code}) if ($partial && refcount($change->{new_code}) == 0); } } print "Done!\n"; exit(0); my @modules_loaded = qw(); sub handler { my ($sig) = @_; die "caught SIG$sig, abort\n" if (!defined($kid)); die "caught SIG$sig after finished\n" if (update_loaded($kid) && (get_stage($kid) eq 'applied')); print STDERR "caught SIG$sig, aborting\n"; rmtree("/var/run/ksplice/updates/$kid") if (-e "/var/run/ksplice/updates/$kid"); cleanup_modules(); exit(1); } sub load_module { my ($module, @params) = @_; push @modules_loaded, ($module =~ m/^(.*)\.ko$/); if (runval_raw("insmod", $module, @params) != 0) { pop @modules_loaded; child_error(); return 0; } return 1; } sub refcount { my ($module) = @_; $module =~ s/-/_/g; foreach(split(/\n/, runstr("lsmod"))) { if (m/^(\S+)\s+[0-9]+\s+([0-9])+\s/) { return $2 if ($1 eq $module); } } return -1; } sub cleanup_modules { foreach my $module (reverse(@modules_loaded)) { runval_raw("rmmod", $module) if(!$nounload); } } sub initialize_abort_code_table { %apply_errors = ( "no_match" => <<'END', Ksplice has aborted the upgrade because Ksplice has been unable to match the object code produced by your current compiler and assembler against the running kernel's object code. If you provided the exact kernel source to the running kernel, then it appears that your current compiler and/or assembler are behaving differently from the compiler and assembler used to build the running kernel. If possible, please use the exact compiler and assembler that were used to build the running kernel. If you are using exactly the same compiler and assembler, consider reporting a bug to PACKAGE_BUGREPORT. END "code_busy" => <<'END', Ksplice has aborted the upgrade because it appears that the code that you are trying to patch is continuously in use by the system. More specifically, Ksplice has been unable to find a moment when one or more of the to-be-patched functions is not on a thread's kernel stack. END "bad_system_map" => <<'END', Ksplice has aborted the upgrade because it appears that the System.map file provided to ksplice-create does not match the running kernel. END "failed_to_find" => <<'END', Ksplice has aborted the upgrade because it was unable to resolve some of the symbols used in the update. END "already_reversed" => <<'END', The Ksplice update that you are attempting to apply has already been applied and reversed. You need to unload the Ksplice modules associated with this update before you can apply this update again. END "missing_export" => <<'END', Ksplice has aborted the upgrade because the symbols exported by the kernel did not match Ksplice's expectations. END "unexpected_running_task" => <<'END', Ksplice has aborted the upgrade because of an unexpected failure during the kernel stack check. Please consider reporting a bug to PACKAGE_BUGREPORT. END "target_not_loaded" => <<'END', Ksplice has aborted the upgrade because one of the modules to be patched by the update was not loaded. If you want to apply this update only to those modules that are loaded, then you should use the --partial option. END "out_of_memory" => <<'END', Ksplice has aborted the upgrade because the kernel ran out of memory. END "call_failed" => <<'END', Ksplice has aborted the upgrade at the request of a one of the pre-application hooks that were included as part of this Ksplice update. This is likely the result of a bug in the patch used to generate this update. END "unexpected" => <<'END', Ksplice has aborted because of an unexpected error. Please consider reporting a bug to PACKAGE_BUGREPORT. END "UNKNOWN" => <<'END', The Ksplice kernel component has returned an error code that this version of ksplice-apply does not understand. END "ok" => <<'END', Ksplice has aborted the upgrade for unknown reasons. Please consider reporting a bug to PACKAGE_BUGREPORT. END ); } sub print_error { my ($kid) = @_; print_abort_error($kid, %apply_errors); } =head1 NAME ksplice-apply - Apply an on-disk Ksplice update to the running kernel =head1 SYNOPSIS B [I] {I | I} =head1 DESCRIPTION B takes as input a Ksplice update, as generated by L, and it applies the update to the running binary kernel. The update may be supplied in the form of a tarball or an unpacked tree. The update is required to have been generated for the running kernel's version. =head1 OPTIONS =over 8 =item B<--debug> Applies the update with debugging output enabled. Recommended only for debugging. =item B<--debugfile=>I Sets the location where debugging output should be saved. Implies --debug. =item B<--partial> Applies the update only to those modules which are loaded. Any modules patched by the update that are not loaded are ignored (without this option, Ksplice aborts if any modules patched by the update are not loaded). =item B<--raw-errors> Print only raw error information designed to be machine-readable on standard error (standard output is still intended to be human-readable). If B fails due to an error from the Ksplice kernel modules, the first line on standard error will be a Ksplice B (see the Ksplice source code for documentation on these codes). Further lines will vary depending on the abort code. If B fails for any other reason, it will output the line C<"OTHER\n">, followed by a human-readable failure message, to standard error. =back =head1 SEE ALSO L, L, L =head1 BUGS Please report bugs to . =head1 AUTHORS Jeff Arnold, Anders Kaseorg, and Tim Abbott =head1 COPYRIGHT Copyright (C) 2007-2009 Ksplice, Inc. This is free software and documentation. You can redistribute and/or modify it under the terms of the GNU General Public License, version 2. =cut ksplice-0.9.9/aclocal.m40000644000000000000000000000367411244274432013536 0ustar rootroot# generated automatically by aclocal 1.9.6 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. dnl @synopsis AC_PROG_PERL_MODULES([MODULES], [ACTION-IF-TRUE], [ACTION-IF-FALSE]) dnl dnl Checks to see if the the given perl modules are available. If true dnl the shell commands in ACTION-IF-TRUE are executed. If not the shell dnl commands in ACTION-IF-FALSE are run. Note if $PERL is not set (for dnl example by calling AC_CHECK_PROG, or AC_PATH_PROG), dnl AC_CHECK_PROG(PERL, perl, perl) will be run. dnl dnl Example: dnl dnl AC_CHECK_PERL_MODULES(Text::Wrap Net::LDAP, , dnl AC_MSG_WARN(Need some Perl modules) dnl dnl @category InstalledPackages dnl @author Dean Povey dnl @version 2002-09-25 dnl @license AllPermissive AC_DEFUN([AC_PROG_PERL_MODULES],[dnl ac_perl_modules="$1" # Make sure we have perl if test -z "$PERL"; then AC_CHECK_PROG(PERL,perl,perl) fi if test "x$PERL" != x; then ac_perl_modules_failed=0 for ac_perl_module in $ac_perl_modules; do AC_MSG_CHECKING(for perl module $ac_perl_module) # Would be nice to log result here, but can't rely on autoconf internals $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 if test $? -ne 0; then AC_MSG_RESULT(no); ac_perl_modules_failed=1 else AC_MSG_RESULT(ok); fi done # Run optional shell commands if test "$ac_perl_modules_failed" = 0; then : $2 else : $3 fi else AC_MSG_WARN(could not find perl) fi])dnl ksplice-0.9.9/AUTHORS0000644000000000000000000000015111244274432012731 0ustar rootrootJeff Arnold Anders Kaseorg Tim Abbott ksplice-0.9.9/ksplice-undo.in0000644000000000000000000001443411244274432014617 0ustar rootroot#!/usr/bin/perl # Copyright (C) 2007-2009 Ksplice, Inc. # Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA # 02110-1301, USA. use strict; use warnings; use lib 'KSPLICE_DATA_DIR'; use Ksplice; my $have_usleep = eval { require Time::HiRes }; my $debug; my $debugon = 0; GetOptions(@common_options, "debug" => \$debugon, "debugfile=s" => \$debug) or pod2usage(1); pod2usage(1) if($help || scalar(@ARGV) != 1); $debugon = 1 if (defined($debug)); $debug = abs_path($debug) if (defined $debug); my $kid = $ARGV[0]; $kid =~ s/^ksplice[-_]//; $kid =~ s/[-_].*$//; my $update = "ksplice_$kid"; my $nounload = runstr("lsmod") =~ m/- $/m; chdir("/sys/module"); if (!update_loaded($kid) && !-e $update && !defined(glob("${update}_*_{o,n,old,new}"))) { print "Ksplice id $kid is not present in the kernel\n"; rmtree("/var/run/ksplice/updates/$kid") if (-e "/var/run/ksplice/updates/$kid"); exit(1); } set_debug_level($kid, $debugon); my $failed = 0; foreach my $module (glob("${update}_*_{o,old}")) { if (!$nounload && runval_raw('rmmod', $module) != 0) { child_error(); error_die(); } } my $have_sysfs = update_loaded($kid); my $stage = ($have_sysfs && get_stage($kid)); if ($stage ne 'applied') { print "Ksplice id $kid is not applied; just cleaning up\n"; } else { set_stage($kid, "reversed"); } $stage = ($have_sysfs && get_stage($kid)); ($stage eq 'reversed') or !$have_sysfs or error_die(); foreach my $module (glob("${update}_*_{n,new}")) { if (!$nounload && runval_raw('rmmod', $module) != 0) { child_error(); error_die(); } } set_stage($kid, "cleanup") if ($have_sysfs); if ($have_usleep) { my $count = 0; while (update_loaded($kid) && $count < 5) { Time::HiRes::usleep(100000); $count++; } } else { sleep(1) if (!update_loaded($kid)); } if (-e "/sys/module/$update") { if (!$nounload && runval_raw('rmmod', $update) != 0) { child_error(); error_die(); } } rmtree("/var/run/ksplice/updates/$kid") if (-e "/var/run/ksplice/updates/$kid"); exit(0); sub error_die { if (!update_loaded($kid)) { die("Error undoing Ksplice update $kid\n"); } print STDERR "Error undoing Ksplice update $kid:\n" unless $raw_errors; print_error($kid); if($debugon) { my $debugfile = get_debug_output($kid, $debug); print("Debugging output saved to $debugfile\n") if $debugfile; } exit(-1); } sub print_error { my ($kid) = @_; my %errors = ( "code_busy" => <<'END', Ksplice has aborted the undo operation because it appears that the code that you are trying to change is continuously in use by the system. More specifically, Ksplice has been unable to find a moment when one or more of the to-be-changed functions is not on a thread's kernel stack. END "module_busy" => <<'END', Ksplice has aborted the undo operation because it appears that the Ksplice update that you are trying to unload is in use by another module. You can find out what module is using the Ksplice update using the lsmod command. END "unexpected_running_task" => <<'END', Ksplice has aborted the undo operation because of an unexpected failure during the kernel stack check. Please consider reporting a bug to PACKAGE_BUGREPORT. END "out_of_memory" => <<'END', Ksplice has aborted the undo operation because the kernel ran out of memory. END "call_failed" => <<'END', Ksplice has aborted the undo operation at the request of a one of the pre-application hooks that were included as part of this Ksplice update. This is likely the result of a bug in the patch used to generate this update. END "cold_update_loaded" => <<'END', Ksplice has aborted the undo operation because the update was applied using the --partial option, and one of the modules that was changed by the update was loaded since the update was applied. You must first unload that (cold patched) module before you can undo this update. END "unexpected" => <<'END', Ksplice has aborted because of an unexpected error. Please consider reporting a bug to PACKAGE_BUGREPORT. END "UNKNOWN" => <<'END', The Ksplice kernel component has returned an error code that this version of ksplice-undo does not understand. END "ok" => <<'END', Ksplice has aborted the undo operation for unknown reasons. Please consider reporting a bug to PACKAGE_BUGREPORT. END ); print_abort_error($kid, %errors); } =head1 NAME ksplice-undo - Undo a Ksplice update that has been applied to the running kernel =head1 SYNOPSIS B [I] I =head1 DESCRIPTION B takes as input a Ksplice identification tag, as reported by L, and it reverses that update within the running binary kernel. =head1 OPTIONS =over 8 =item B<--debug> Reverses the update with debugging output enabled. Recommended only for debugging. =item B<--debugfile=>I Sets the location where debugging output should be saved. Implies --debug. =item B<--raw-errors> Print only raw error information designed to be machine-readable on standard error (standard output is still intended to be human-readable). If B fails due to an error from the Ksplice kernel modules, the first line on standard error will be a Ksplice B (see the Ksplice source code for documentation on these codes). Further lines will vary depending on the abort code. If B fails for any other reason, it will output the line C<"OTHER\n">, followed by a human-readable failure message, to standard error. =back =head1 SEE ALSO L, L, L =head1 BUGS Please report bugs to . =head1 AUTHORS Jeff Arnold, Anders Kaseorg, and Tim Abbott =head1 COPYRIGHT Copyright (C) 2007-2009 Ksplice, Inc. This is free software and documentation. You can redistribute and/or modify it under the terms of the GNU General Public License, version 2. =cut ksplice-0.9.9/objcommon.c0000644000000000000000000002213311244274432014014 0ustar rootroot/* Copyright (C) 2007-2009 Ksplice, Inc. * Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA * 02110-1301, USA. */ #define _GNU_SOURCE #include "objcommon.h" #include #define arelentp_init(x) *(x) = NULL IMPLEMENT_HASH_TYPE(arelent *, arelentp_hash, arelentp_hash_init, arelentp_hash_free, arelentp_hash_lookup, arelentp_init); #define label_mapp_init(map) *(map) = NULL IMPLEMENT_HASH_TYPE(struct label_map *, label_mapp_hash, label_mapp_hash_init, label_mapp_hash_free, label_mapp_hash_lookup, label_mapp_init); #define asymbolpp_init(symp) *(symp) = NULL IMPLEMENT_HASH_TYPE(asymbol **, asymbolpp_hash, asymbolpp_hash_init, asymbolpp_hash_free, asymbolpp_hash_lookup, asymbolpp_init); #define string_init(str) *(str) = NULL IMPLEMENT_HASH_TYPE(const char *, string_hash, string_hash_init, string_hash_free, string_hash_lookup, string_init); void vec_do_reserve(void **data, size_t *mem_size, size_t new_size) { if (new_size > *mem_size || new_size * 2 < *mem_size) { if (new_size < *mem_size * 2) new_size = *mem_size * 2; *data = realloc(*data, new_size); assert(new_size == 0 || *data != NULL); *mem_size = new_size; } } void get_syms(bfd *abfd, struct asymbolp_vec *syms) { long storage_needed = bfd_get_symtab_upper_bound(abfd); if (storage_needed == 0) return; assert(storage_needed >= 0); vec_init(syms); vec_reserve(syms, storage_needed); vec_resize(syms, bfd_canonicalize_symtab(abfd, syms->data)); assert(syms->size >= 0); } struct superbfd *fetch_superbfd(bfd *abfd) { assert(abfd != NULL); if (abfd->usrdata != NULL) return abfd->usrdata; struct superbfd *sbfd = malloc(sizeof(*sbfd)); assert(sbfd != NULL); abfd->usrdata = sbfd; sbfd->abfd = abfd; get_syms(abfd, &sbfd->syms); vec_init(&sbfd->new_syms); sbfd->new_supersects = NULL; return sbfd; } struct supersect *fetch_supersect(struct superbfd *sbfd, asection *sect) { assert(sect != NULL); assert(!bfd_is_const_section(sect)); if (sect->userdata != NULL) return sect->userdata; struct supersect *new = malloc(sizeof(*new)); assert(new != NULL); sect->userdata = new; new->parent = sbfd; new->name = sect->name; new->flags = bfd_get_section_flags(sbfd->abfd, sect); new->keep = true; new->match_data_early = false; new->symbol = sect->symbol; vec_init(&new->contents); vec_resize(&new->contents, bfd_get_section_size(sect)); assert(bfd_get_section_contents (sbfd->abfd, sect, new->contents.data, 0, new->contents.size)); new->alignment = bfd_get_section_alignment(sbfd->abfd, sect); new->entsize = sect->entsize; vec_init(&new->relocs); vec_reserve(&new->relocs, bfd_get_reloc_upper_bound(sbfd->abfd, sect)); vec_resize(&new->relocs, bfd_canonicalize_reloc(sbfd->abfd, sect, new->relocs.data, sbfd->syms.data)); assert(new->relocs.size >= 0); vec_init(&new->new_relocs); vec_init(&new->syms); asymbol **symp; for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size; symp++) { asymbol *sym = *symp; if (sym->section == sect && (sym->flags & BSF_SECTION_SYM) == 0) *vec_grow(&new->syms, 1) = sym; } vec_init(&new->spans); arelentp_hash_init(&new->reloc_hash); arelent **relocp; for (relocp = new->relocs.data; relocp < new->relocs.data + new->relocs.size; relocp++) { arelent *reloc = *relocp; char *key = strprintf("%lx", (unsigned long)reloc->address); arelent **hash_relocp = arelentp_hash_lookup(&new->reloc_hash, key, TRUE); free(key); *hash_relocp = reloc; } return new; } struct supersect *new_supersect(struct superbfd *sbfd, const char *name) { struct supersect *ss; for (ss = sbfd->new_supersects; ss != NULL; ss = ss->next) { if (strcmp(name, ss->name) == 0) return ss; } struct supersect *new = malloc(sizeof(*new)); new->parent = sbfd; new->name = name; new->next = sbfd->new_supersects; sbfd->new_supersects = new; new->flags = SEC_ALLOC | SEC_HAS_CONTENTS | SEC_RELOC; new->keep = true; vec_init(&new->contents); new->alignment = 0; new->entsize = 0; vec_init(&new->relocs); vec_init(&new->new_relocs); new->type = SS_TYPE_KSPLICE; return new; } void supersect_move(struct supersect *dest_ss, struct supersect *src_ss) { *dest_ss = *src_ss; vec_init(&src_ss->contents); vec_init(&src_ss->relocs); vec_init(&src_ss->new_relocs); vec_init(&src_ss->syms); } void *sect_do_grow(struct supersect *ss, size_t n, size_t size, int alignment) { if (ss->alignment < ffs(alignment) - 1) ss->alignment = ffs(alignment) - 1; int pad = align(ss->contents.size, alignment) - ss->contents.size; void *out = vec_grow(&ss->contents, pad + n * size); memset(out, 0, pad + n * size); return out + pad; } static void mod_relocs(struct arelentp_vec *dest_relocs, struct arelentp_vec *src_relocs, bfd_size_type start, bfd_size_type end, bfd_size_type mod) { arelent **relocp; for (relocp = src_relocs->data; relocp < src_relocs->data + src_relocs->size; relocp++) { if ((*relocp)->address >= start && (*relocp)->address < end) { arelent *reloc = malloc(sizeof(*reloc)); assert(reloc != NULL); *reloc = **relocp; reloc->address += mod; *vec_grow(dest_relocs, 1) = reloc; } } } static void mod_symbols(struct asymbolp_vec *dest_syms, struct asymbolp_vec *src_syms, bfd_size_type start, bfd_size_type end, bfd_size_type mod) { asymbol **symp; for (symp = src_syms->data; symp < src_syms->data + src_syms->size; symp++) { /* must mutate symbols in-place since there are pointers to them in relocations elsewhere */ asymbol *sym = *symp; if (sym->value >= start && sym->value < end) { sym->value += mod; *vec_grow(dest_syms, 1) = sym; } } } void sect_do_copy(struct supersect *dest_ss, void *dest, struct supersect *src_ss, const void *src, size_t n) { memcpy(dest, src, n); bfd_size_type start = addr_offset(src_ss, src); bfd_size_type end = start + n; bfd_size_type mod = addr_offset(dest_ss, dest) - start; mod_relocs(&dest_ss->relocs, &src_ss->relocs, start, end, mod); mod_relocs(&dest_ss->new_relocs, &src_ss->new_relocs, start, end, mod); mod_symbols(&dest_ss->syms, &src_ss->syms, start, end, mod); } bfd_vma addr_offset(struct supersect *ss, const void *addr) { return (void *)addr - ss->contents.data; } bfd_vma reloc_offset(struct supersect *ss, arelent *reloc) { int size = bfd_get_reloc_size(reloc->howto); bfd_vma x = bfd_get(size * 8, ss->parent->abfd, ss->contents.data + reloc->address); x &= reloc->howto->src_mask; x >>= reloc->howto->bitpos; bfd_vma signbit = reloc->howto->dst_mask >> reloc->howto->bitpos; signbit &= ~(signbit >> 1); switch (reloc->howto->complain_on_overflow) { case complain_overflow_signed: case complain_overflow_bitfield: x |= -(x & signbit); break; case complain_overflow_unsigned: break; default: DIE; } x <<= reloc->howto->rightshift; bfd_vma add = reloc->addend; if (reloc->howto->pc_relative) { if (!reloc->howto->pcrel_offset) add += reloc->address; } return x + add; } arelent *find_reloc(struct supersect *ss, const void *addr) { bfd_vma address = addr_offset(ss, addr); char *key = strprintf("%lx", (unsigned long)address); arelent **relocp = arelentp_hash_lookup(&ss->reloc_hash, key, FALSE); free(key); return relocp != NULL ? *relocp : NULL; } bfd_vma read_reloc(struct supersect *ss, const void *addr, size_t size, asymbol **symp) { bfd_vma val = bfd_get(size * 8, ss->parent->abfd, addr); arelent *reloc = find_reloc(ss, addr); if (reloc == NULL) { if (symp != NULL) *symp = *bfd_abs_section_ptr->symbol_ptr_ptr; return val; } if (symp != NULL) *symp = *reloc->sym_ptr_ptr; else if (*reloc->sym_ptr_ptr != bfd_abs_section_ptr->symbol) fprintf(stderr, "warning: unexpected " "non-absolute relocation at %s+%lx\n", ss->name, (unsigned long)addr_offset(ss, addr)); return reloc_offset(ss, reloc); } const void *read_pointer(struct supersect *ss, void *const *addr, struct supersect **data_ssp) { asymbol *sym; bfd_vma offset = read_reloc(ss, addr, sizeof(*addr), &sym); if (bfd_is_abs_section(sym->section) && sym->value + offset == 0) return NULL; if (bfd_is_const_section(sym->section)) { fprintf(stderr, "warning: unexpected relocation to const " "section at %s+%lx\n", ss->name, (unsigned long)addr_offset(ss, addr)); return NULL; } struct supersect *data_ss = fetch_supersect(ss->parent, sym->section); if (data_ssp != NULL) *data_ssp = data_ss; return data_ss->contents.data + sym->value + offset; } const char *read_string(struct supersect *ss, const char *const *addr) { return read_pointer(ss, (void *const *)addr, NULL); } ksplice-0.9.9/ksplice-obj.pl.in0000644000000000000000000001057311244274432015036 0ustar rootroot#!/usr/bin/perl # Copyright (C) 2008-2009 Ksplice, Inc. # Authors: Anders Kaseorg, Jeff Arnold, Tim Abbott # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA # 02110-1301, USA. use strict; use warnings; use lib 'KSPLICE_DATA_DIR'; use Ksplice; $Verbose::level = $ENV{KSPLICE_VERBOSE} if (defined $ENV{KSPLICE_VERBOSE}); sub empty_diff { my ($out) = @_; my ($obj) = $out =~ /^(.*)\.KSPLICE$/ or die; unlink "$obj.KSPLICE_new_code" if (-e "$obj.KSPLICE_new_code"); unlink "$obj.KSPLICE_old_code" if (-e "$obj.KSPLICE_old_code"); open OUT, '>', "$out.tmp"; close OUT; rename "$out.tmp", $out; } sub do_snap { my ($out) = @_; my ($obj) = $out =~ /^(.*)\.KSPLICE$/ or die; die if (!-e $obj); unlink "$obj.KSPLICE_pre" if (-e "$obj.KSPLICE_pre"); empty_diff($out); } sub do_diff { my ($out) = @_; my ($obj) = $out =~ /^(.*)\.KSPLICE$/ or die; my $obj_pre = "$obj.KSPLICE_pre"; die if (!-e $obj); die "Patch creates new object $obj" if (!-e $obj_pre); if (system('cmp', '-s', '--', $obj_pre, $obj) == 0) { unlink $obj_pre; return empty_diff($out); } runval("$libexecdir/ksplice-objmanip", $obj, "$obj.KSPLICE_new_code", "keep-new-code", "$obj.KSPLICE_pre", $ENV{KSPLICE_KID}); return empty_diff($out) if (!-e "$obj.KSPLICE_new_code"); open OUT, '>', "$out.tmp"; print OUT "1\n"; close OUT; rename "$out.tmp", $out; runval("$libexecdir/ksplice-objmanip", $obj_pre, "$obj.KSPLICE_old_code", "keep-old-code"); } sub do_old_code { my ($out) = @_; my ($obj) = $out =~ /^(.*)\.KSPLICE_old_code$/ or die; my $obj_pre = "$obj.KSPLICE_pre"; -e $obj_pre or $obj_pre = $obj; runval("$libexecdir/ksplice-objmanip", $obj_pre, "$obj.KSPLICE_old_code", "keep-old-code"); } sub link_objs { my ($out, @ins) = @_; if (@ins == 0) { runval(shellwords($ENV{AR}), "rcs", $out); } elsif (@ins == 1) { copy @ins, $out; } else { runval(shellwords($ENV{LD}), "-r", "-o", $out, @ins); } } sub do_combine { my ($out, @ins) = @_; my @new_code_objs; my @old_code_objs; foreach my $in (@ins) { if (my ($obj) = $in =~ /^(.*)\.KSPLICE$/) { next if (!-s $in); push @new_code_objs, "$obj.KSPLICE_new_code"; push @old_code_objs, "$obj.KSPLICE_old_code"; } elsif (($obj) = $in =~ /^(.*)\.KSPLICE_old_code$/) { push @old_code_objs, "$obj.KSPLICE_old_code" unless (@old_code_objs && $old_code_objs[$#old_code_objs] eq "$obj.KSPLICE_old_code"); } elsif ("$in.KSPLICE" eq $out) { my $pre = "$in.KSPLICE_pre"; if (system('cmp', '-s', '--', $pre, $in) == 0) { unlink $pre; } } else { die "Unexpected input $in for $out"; } } return empty_diff($out) unless (@old_code_objs); my ($obj) = $out =~ /^(.*)\.KSPLICE$/ or die; link_objs("$obj.KSPLICE_new_code", @new_code_objs); link_objs("$obj.KSPLICE_old_code", @old_code_objs); open OUT, '>', "$out.tmp"; print OUT "1\n"; close OUT; rename "$out.tmp", $out; } sub do_finalize { my ($in, $out, $target) = @_; my $ret = runval_raw("$libexecdir/ksplice-objmanip", $in, $out, "finalize", $target); if ($ret == 0) { } elsif ($ret >> 8 == 66) { runval(shellwords($ENV{AR}), "rcs", $out); } else { child_error(); } } sub do_rmsyms { my ($in, $out) = @_; runval("$libexecdir/ksplice-objmanip", $in, $out, "rmsyms"); } sub do_system_map_lookup { my ($symarg) = @_; open(SYMS, "<", "$ENV{KSPLICE_CONFIG_DIR}/System.map") or die; my $line; while (defined($line = )) { my ($addr, $type, $sym, $mod) = split(/\s+/, $line); if ($sym eq $symarg) { print $addr; last; } } close(SYMS); } my %handlers = ( 'snap' => \&do_snap, 'diff' => \&do_diff, 'old_code' => \&do_old_code, 'combine' => \&do_combine, 'finalize' => \&do_finalize, 'rmsyms' => \&do_rmsyms, 'system_map_lookup' => \&do_system_map_lookup, ); my ($cmd, @args) = @ARGV; if (exists $handlers{$cmd}) { my $handler = $handlers{$cmd}; &$handler(@args); } else { print "Usage: ksplice-obj.pl ", join('|', keys %handlers), " ...\n"; exit(1); }; ksplice-0.9.9/configure0000755000000000000000000041506211244274432013603 0ustar rootroot#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for Ksplice 0.9.9. # # Report bugs to . # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # PATH needs CR # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) as_nl=' ' IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 { (exit 1); exit 1; } fi # Work around bugs in pre-3.0 UWIN ksh. for as_var in ENV MAIL MAILPATH do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # CDPATH. $as_unset CDPATH if test "x$CONFIG_SHELL" = x; then if (eval ":") 2>/dev/null; then as_have_required=yes else as_have_required=no fi if test $as_have_required = yes && (eval ": (as_func_return () { (exit \$1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = \"\$1\" ); then : else exitcode=1 echo positional parameters were not saved. fi test \$exitcode = 0) || { (exit 1); exit 1; } ( as_lineno_1=\$LINENO as_lineno_2=\$LINENO test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } ") 2> /dev/null; then : else as_candidate_shells= as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. case $as_dir in /*) for as_base in sh bash ksh sh5; do as_candidate_shells="$as_candidate_shells $as_dir/$as_base" done;; esac done IFS=$as_save_IFS for as_shell in $as_candidate_shells $SHELL; do # Try only shells that exist, to save several forks. if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { ("$as_shell") 2> /dev/null <<\_ASEOF if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi : _ASEOF }; then CONFIG_SHELL=$as_shell as_have_required=yes if { "$as_shell" 2> /dev/null <<\_ASEOF if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi : (as_func_return () { (exit $1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = "$1" ); then : else exitcode=1 echo positional parameters were not saved. fi test $exitcode = 0) || { (exit 1); exit 1; } ( as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } _ASEOF }; then break fi fi done if test "x$CONFIG_SHELL" != x; then for as_var in BASH_ENV ENV do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test $as_have_required = no; then echo This script requires a shell more modern than all the echo shells that I found on your system. Please install a echo modern shell, or manually run the script under such a echo shell if you do have one. { (exit 1); exit 1; } fi fi fi (eval "as_func_return () { (exit \$1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = \"\$1\" ); then : else exitcode=1 echo positional parameters were not saved. fi test \$exitcode = 0") || { echo No shell found that supports shell functions. echo Please tell autoconf@gnu.org about your system, echo including any error possibly output before this echo message } as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line after each line using $LINENO; the second 'sed' # does the real work. The second script uses 'N' to pair each # line-number line with the line containing $LINENO, and appends # trailing '-' during substitution so that $LINENO is not a special # case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # scripts with optimization help from Paolo Bonzini. Blame Lee # E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in -n*) case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir fi echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='Ksplice' PACKAGE_TARNAME='ksplice' PACKAGE_VERSION='0.9.9' PACKAGE_STRING='Ksplice 0.9.9' PACKAGE_BUGREPORT='devel@ksplice.com' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datarootdir datadir sysconfdir sharedstatedir localstatedir includedir oldincludedir docdir infodir htmldir dvidir pdfdir psdir libdir localedir mandir DEFS ECHO_C ECHO_N ECHO_T LIBS build_alias host_alias target_alias KSPLICE_API_VERSION CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP GREP EGREP PATCH POD2MAN PERL LIBOBJS LTLIBOBJS' ac_subst_files='' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` eval enable_$ac_feature=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` eval enable_$ac_feature=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/[-.]/_/g'` eval with_$ac_package=\$ac_optarg ;; -without-* | --without-*) ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/[-.]/_/g'` eval with_$ac_package=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) { echo "$as_me: error: unrecognized option: $ac_option Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 { (exit 1); exit 1; }; } eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` { echo "$as_me: error: missing argument to $ac_option" >&2 { (exit 1); exit 1; }; } fi # Be sure to have absolute directory names. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; } done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || { echo "$as_me: error: Working directory cannot be determined" >&2 { (exit 1); exit 1; }; } test "X$ac_ls_di" = "X$ac_pwd_ls_di" || { echo "$as_me: error: pwd does not report name of working directory" >&2 { (exit 1); exit 1; }; } # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$0" || $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$0" : 'X\(//\)[^/]' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X"$0" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 { (exit 1); exit 1; }; } pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures Ksplice 0.9.9 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/ksplice] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of Ksplice 0.9.9:";; esac cat <<\_ACEOF Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-libbfd=FILE path to libbfd.a --with-libiberty=FILE path to libiberty.a --with-libz=FILE path to libz.a --with-bfd-include-dir=DIR path to directory containing bfd.h Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF Ksplice configure 0.9.9 generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by Ksplice $as_me 0.9.9, which was generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac done done $as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------------- ## ## File substitutions. ## ## ------------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo cat confdefs.h echo fi test "$ac_signal" != 0 && echo "$as_me: caught signal $ac_signal" echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer explicitly selected file to automatically selected ones. if test -n "$CONFIG_SITE"; then set x "$CONFIG_SITE" elif test "x$prefix" != xNONE; then set x "$prefix/share/config.site" "$prefix/etc/config.site" else set x "$ac_default_prefix/share/config.site" \ "$ac_default_prefix/etc/config.site" fi shift for ac_site_file do if test -r "$ac_site_file"; then { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special # files actually), so we avoid doing that. if test -f "$cache_file"; then { echo "$as_me:$LINENO: loading cache $cache_file" >&5 echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { echo "$as_me:$LINENO: creating cache $cache_file" >&5 echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 echo "$as_me: former value: $ac_old_val" >&2;} { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 echo "$as_me: current value: $ac_new_val" >&2;} ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu KSPLICE_API_VERSION=2 # Check whether --with-libbfd was given. if test "${with_libbfd+set}" = set; then withval=$with_libbfd; ac_libbfd=$withval else ac_libbfd=NONE fi # Check whether --with-libiberty was given. if test "${with_libiberty+set}" = set; then withval=$with_libiberty; ac_libiberty=$withval else ac_libiberty=NONE fi # Check whether --with-libz was given. if test "${with_libz+set}" = set; then withval=$with_libz; ac_libz=$withval else ac_libz=NONE fi # Check whether --with-bfd-include-dir was given. if test "${with_bfd_include_dir+set}" = set; then withval=$with_bfd_include_dir; ac_bfd_include_dir=$withval else ac_bfd_include_dir=NONE fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } # Provide some information about the compiler. echo "$as_me:$LINENO: checking for C compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (ac_try="$ac_compiler --version >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler --version >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -v >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -v >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -V >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -V >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; } ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # # List of possible output files, starting from the most likely. # The algorithm is not robust to junk in `.', hence go to wildcards (a.*) # only as a last resort. b.out is created by i960 compilers. ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' # # The IRIX 6 linker writes into existing files which may not be # executable, retaining their permissions. Remove them first so a # subsequent execution test works. ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { (ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link_default") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi { echo "$as_me:$LINENO: result: $ac_file" >&5 echo "${ECHO_T}$ac_file" >&6; } if test -z "$ac_file"; then echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: C compiler cannot create executables See \`config.log' for more details." >&5 echo "$as_me: error: C compiler cannot create executables See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } fi ac_exeext=$ac_cv_exeext # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { echo "$as_me:$LINENO: checking whether the C compiler works" >&5 echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; } # FIXME: These cross compiler hacks should be removed for Autoconf 3.0 # If not cross compiling, check that we can run a simple program. if test "$cross_compiling" != yes; then if { ac_try='./$ac_file' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { echo "$as_me:$LINENO: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&5 echo "$as_me: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi fi fi { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } rm -f a.out a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; } { echo "$as_me:$LINENO: result: $cross_compiling" >&5 echo "${ECHO_T}$cross_compiling" >&6; } { echo "$as_me:$LINENO: checking for suffix of executables" >&5 echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; } if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest$ac_cv_exeext { echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 echo "${ECHO_T}$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT { echo "$as_me:$LINENO: checking for suffix of object files" >&5 echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; } if test "${ac_cv_objext+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 echo "${ECHO_T}$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } GCC=`test $ac_compiler_gnu = yes && echo yes` ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 CFLAGS="" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_c89=$ac_arg else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { echo "$as_me:$LINENO: result: none needed" >&5 echo "${ECHO_T}none needed" >&6; } ;; xno) { echo "$as_me:$LINENO: result: unsupported" >&5 echo "${ECHO_T}unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test "$ac_libz" = "NONE"; then { echo "$as_me:$LINENO: checking for zlibVersion in -lz" >&5 echo $ECHO_N "checking for zlibVersion in -lz... $ECHO_C" >&6; } if test "${ac_cv_lib_z_zlibVersion+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char zlibVersion (); int main () { return zlibVersion (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_z_zlibVersion=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_z_zlibVersion=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_z_zlibVersion" >&5 echo "${ECHO_T}$ac_cv_lib_z_zlibVersion" >&6; } if test $ac_cv_lib_z_zlibVersion = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBZ 1 _ACEOF LIBS="-lz $LIBS" fi else LIBS="$ac_libz $LIBS" fi if test "$ac_libiberty" = "NONE"; then { echo "$as_me:$LINENO: checking for objalloc_create in -liberty" >&5 echo $ECHO_N "checking for objalloc_create in -liberty... $ECHO_C" >&6; } if test "${ac_cv_lib_iberty_objalloc_create+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-liberty $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char objalloc_create (); int main () { return objalloc_create (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_iberty_objalloc_create=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_iberty_objalloc_create=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_iberty_objalloc_create" >&5 echo "${ECHO_T}$ac_cv_lib_iberty_objalloc_create" >&6; } if test $ac_cv_lib_iberty_objalloc_create = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBIBERTY 1 _ACEOF LIBS="-liberty $LIBS" fi else LIBS="$ac_libiberty $LIBS" fi if test "$ac_libbfd" = "NONE"; then ac_libbfd=auto { echo "$as_me:$LINENO: checking for bfd_openr in -lbfd" >&5 echo $ECHO_N "checking for bfd_openr in -lbfd... $ECHO_C" >&6; } if test "${ac_cv_lib_bfd_bfd_openr+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbfd $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char bfd_openr (); int main () { return bfd_openr (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_bfd_bfd_openr=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_bfd_bfd_openr=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_bfd_bfd_openr" >&5 echo "${ECHO_T}$ac_cv_lib_bfd_bfd_openr" >&6; } if test $ac_cv_lib_bfd_bfd_openr = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBBFD 1 _ACEOF LIBS="-lbfd $LIBS" else ac_libbfd=NONE fi else LIBS="$ac_libbfd $LIBS" fi if test "$ac_bfd_include_dir" != "NONE"; then CPPFLAGS="$CPPFLAGS -I$ac_bfd_include_dir" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { echo "$as_me:$LINENO: result: $CPP" >&5 echo "${ECHO_T}$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&5 echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } if test "${ac_cv_path_GREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Extract the first word of "grep ggrep" to use in msg output if test -z "$GREP"; then set dummy grep ggrep; ac_prog_name=$2 if test "${ac_cv_path_GREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break ac_count=`expr $ac_count + 1` if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS fi GREP="$ac_cv_path_GREP" if test -z "$GREP"; then { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} { (exit 1); exit 1; }; } fi else ac_cv_path_GREP=$GREP fi fi { echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 echo "${ECHO_T}$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { echo "$as_me:$LINENO: checking for egrep" >&5 echo $ECHO_N "checking for egrep... $ECHO_C" >&6; } if test "${ac_cv_path_EGREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else # Extract the first word of "egrep" to use in msg output if test -z "$EGREP"; then set dummy egrep; ac_prog_name=$2 if test "${ac_cv_path_EGREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break ac_count=`expr $ac_count + 1` if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS fi EGREP="$ac_cv_path_EGREP" if test -z "$EGREP"; then { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} { (exit 1); exit 1; }; } fi else ac_cv_path_EGREP=$EGREP fi fi fi { echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 echo "${ECHO_T}$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { echo "$as_me:$LINENO: checking for ANSI C header files" >&5 echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } if test "${ac_cv_header_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_header_stdc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi { echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 echo "${ECHO_T}$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then cat >>confdefs.h <<\_ACEOF #define STDC_HEADERS 1 _ACEOF fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in bfd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## -------------------------------- ## ## Report this to devel@ksplice.com ## ## -------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF else BFD_H="no" fi done { echo "$as_me:$LINENO: checking for struct bfd_hash_table.entsize" >&5 echo $ECHO_N "checking for struct bfd_hash_table.entsize... $ECHO_C" >&6; } if test "${ac_cv_member_struct_bfd_hash_table_entsize+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { static struct bfd_hash_table ac_aggr; if (ac_aggr.entsize) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_member_struct_bfd_hash_table_entsize=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { static struct bfd_hash_table ac_aggr; if (sizeof ac_aggr.entsize) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_member_struct_bfd_hash_table_entsize=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_member_struct_bfd_hash_table_entsize=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_member_struct_bfd_hash_table_entsize" >&5 echo "${ECHO_T}$ac_cv_member_struct_bfd_hash_table_entsize" >&6; } if test $ac_cv_member_struct_bfd_hash_table_entsize = yes; then CPPFLAGS="$CPPFLAGS -DBFD_HASH_TABLE_HAS_ENTSIZE" fi if ! test -e "objmanip-static"; then if test "$ac_libbfd" = "NONE"; then echo echo "Ksplice could not locate libbfd.a and/or libiberty.a on your system." echo "You can obtain these libraries from the GNU binutils collection." echo "These libraries are available on many Linux distributions as a" echo "package called 'binutils-dev' or 'binutils-devel'." echo "If your distribution does not provide GNU binutils, you can install" echo "GNU binutils from source -- see http://www.gnu.org/software/binutils/." echo echo "If these libraries are already installed on your system, then you need" echo "to tell Ksplice where to find them by running configure again:" echo echo " ./configure --with-libbfd= --with-libiberty=" echo echo "Depending on the host system you may also need to provide zlib:" echo echo " ./configure ... --with-libz=" echo exit 1 fi if test "$BFD_H" = "no"; then echo echo "Ksplice could not locate bfd.h on your system." echo "If this header file is already installed on your system, then you need" echo "to tell Ksplice where to find it by running configure again:" echo echo " ./configure --with-bfd-include-dir=" echo exit 1 fi fi # Extract the first word of "patch", so it can be a program name with args. set dummy patch; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_path_PATCH+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $PATCH in [\\/]* | ?:[\\/]*) ac_cv_path_PATCH="$PATCH" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_PATCH="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PATCH=$ac_cv_path_PATCH if test -n "$PATCH"; then { echo "$as_me:$LINENO: result: $PATCH" >&5 echo "${ECHO_T}$PATCH" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi # Extract the first word of "pod2man", so it can be a program name with args. set dummy pod2man; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_path_POD2MAN+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else case $POD2MAN in [\\/]* | ?:[\\/]*) ac_cv_path_POD2MAN="$POD2MAN" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_POD2MAN="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi POD2MAN=$ac_cv_path_POD2MAN if test -n "$POD2MAN"; then { echo "$as_me:$LINENO: result: $POD2MAN" >&5 echo "${ECHO_T}$POD2MAN" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "$PATCH" = ""; then echo echo "Ksplice could not locate patch on your system." echo exit 1 fi if test "$POD2MAN" = ""; then echo echo "Ksplice could not locate pod2man on your system." echo exit 1 fi ac_perl_modules="Cwd Getopt::Long File::Basename File::Copy File::Path File::Spec::Functions File::Temp Fatal IPC::Open2 IPC::Open3 Pod::Usage Text::ParseWords" # Make sure we have perl if test -z "$PERL"; then # Extract the first word of "perl", so it can be a program name with args. set dummy perl; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_PERL+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$PERL"; then ac_cv_prog_PERL="$PERL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_PERL="perl" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi PERL=$ac_cv_prog_PERL if test -n "$PERL"; then { echo "$as_me:$LINENO: result: $PERL" >&5 echo "${ECHO_T}$PERL" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi if test "x$PERL" != x; then ac_perl_modules_failed=0 for ac_perl_module in $ac_perl_modules; do { echo "$as_me:$LINENO: checking for perl module $ac_perl_module" >&5 echo $ECHO_N "checking for perl module $ac_perl_module... $ECHO_C" >&6; } # Would be nice to log result here, but can't rely on autoconf internals $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 if test $? -ne 0; then { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; }; ac_perl_modules_failed=1 else { echo "$as_me:$LINENO: result: ok" >&5 echo "${ECHO_T}ok" >&6; }; fi done # Run optional shell commands if test "$ac_perl_modules_failed" = 0; then : else : { { echo "$as_me:$LINENO: error: Missing some required perl modules" >&5 echo "$as_me: error: Missing some required perl modules" >&2;} { (exit 1); exit 1; }; } fi else { echo "$as_me:$LINENO: WARNING: could not find perl" >&5 echo "$as_me: WARNING: could not find perl" >&2;} fi ac_config_files="$ac_config_files Makefile kmodsrc/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 echo "$as_me: creating $CONFIG_STATUS" >&6;} cat >$CONFIG_STATUS <<_ACEOF #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # PATH needs CR # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) as_nl=' ' IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 { (exit 1); exit 1; } fi # Work around bugs in pre-3.0 UWIN ksh. for as_var in ENV MAIL MAILPATH do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # CDPATH. $as_unset CDPATH as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line after each line using $LINENO; the second 'sed' # does the real work. The second script uses 'N' to pair each # line-number line with the line containing $LINENO, and appends # trailing '-' during substitution so that $LINENO is not a special # case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # scripts with optimization help from Paolo Bonzini. Blame Lee # E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in -n*) case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir fi echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 # Save the log message, to keep $[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by Ksplice $as_me 0.9.9, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ Ksplice config.status 0.9.9 configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2006 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If no file are specified by the user, then we need to provide default # value. By we need to know if files were specified by the user. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) echo "$ac_cs_version"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift CONFIG_FILES="$CONFIG_FILES $ac_optarg" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) { echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *) ac_config_targets="$ac_config_targets $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF if \$ac_cs_recheck; then echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 CONFIG_SHELL=$SHELL export CONFIG_SHELL exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "kmodsrc/Makefile") CONFIG_FILES="$CONFIG_FILES kmodsrc/Makefile" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || { echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } # # Set up the sed scripts for CONFIG_FILES section. # # No need to generate the scripts if there are no CONFIG_FILES. # This happens for instance when ./config.status config.h if test -n "$CONFIG_FILES"; then _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF SHELL!$SHELL$ac_delim PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim PACKAGE_NAME!$PACKAGE_NAME$ac_delim PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim PACKAGE_STRING!$PACKAGE_STRING$ac_delim PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim exec_prefix!$exec_prefix$ac_delim prefix!$prefix$ac_delim program_transform_name!$program_transform_name$ac_delim bindir!$bindir$ac_delim sbindir!$sbindir$ac_delim libexecdir!$libexecdir$ac_delim datarootdir!$datarootdir$ac_delim datadir!$datadir$ac_delim sysconfdir!$sysconfdir$ac_delim sharedstatedir!$sharedstatedir$ac_delim localstatedir!$localstatedir$ac_delim includedir!$includedir$ac_delim oldincludedir!$oldincludedir$ac_delim docdir!$docdir$ac_delim infodir!$infodir$ac_delim htmldir!$htmldir$ac_delim dvidir!$dvidir$ac_delim pdfdir!$pdfdir$ac_delim psdir!$psdir$ac_delim libdir!$libdir$ac_delim localedir!$localedir$ac_delim mandir!$mandir$ac_delim DEFS!$DEFS$ac_delim ECHO_C!$ECHO_C$ac_delim ECHO_N!$ECHO_N$ac_delim ECHO_T!$ECHO_T$ac_delim LIBS!$LIBS$ac_delim build_alias!$build_alias$ac_delim host_alias!$host_alias$ac_delim target_alias!$target_alias$ac_delim KSPLICE_API_VERSION!$KSPLICE_API_VERSION$ac_delim CC!$CC$ac_delim CFLAGS!$CFLAGS$ac_delim LDFLAGS!$LDFLAGS$ac_delim CPPFLAGS!$CPPFLAGS$ac_delim ac_ct_CC!$ac_ct_CC$ac_delim EXEEXT!$EXEEXT$ac_delim OBJEXT!$OBJEXT$ac_delim CPP!$CPP$ac_delim GREP!$GREP$ac_delim EGREP!$EGREP$ac_delim PATCH!$PATCH$ac_delim POD2MAN!$POD2MAN$ac_delim PERL!$PERL$ac_delim LIBOBJS!$LIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 53; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} { (exit 1); exit 1; }; } else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` if test -n "$ac_eof"; then ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` ac_eof=`expr $ac_eof + 1` fi cat >>$CONFIG_STATUS <<_ACEOF cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof /@[a-zA-Z_][a-zA-Z_0-9]*@/!b end _ACEOF sed ' s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g s/^/s,@/; s/!/@,|#_!!_#|/ :n t n s/'"$ac_delim"'$/,g/; t s/$/\\/; p N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n ' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF :end s/|#_!!_#|//g CEOF$ac_eof _ACEOF # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/ s/:*\${srcdir}:*/:/ s/:*@srcdir@:*/:/ s/^\([^=]*=[ ]*\):*/\1/ s/:*$// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF fi # test -n "$CONFIG_FILES" for ac_tag in :F $CONFIG_FILES do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 echo "$as_me: error: Invalid tag $ac_tag." >&2;} { (exit 1); exit 1; }; };; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 echo "$as_me: error: cannot find input file: $ac_f" >&2;} { (exit 1); exit 1; }; };; esac ac_file_inputs="$ac_file_inputs $ac_f" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input="Generated from "`IFS=: echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} fi case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin";; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` { as_dir="$ac_dir" case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 echo "$as_me: error: cannot create directory $as_dir" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= case `sed -n '/datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p ' $ac_file_inputs` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s&@configure_input@&$configure_input&;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&5 echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out"; rm -f "$tmp/out";; *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; esac ;; esac done # for ac_tag { (exit 0); exit 0; } _ACEOF chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi ksplice-0.9.9/ksplice-patch/0000755000000000000000000000000011244274432014413 5ustar rootrootksplice-0.9.9/ksplice-patch/ksplice-patch.h0000644000000000000000000001131211244274432017311 0ustar rootroot#ifndef _KSPLICE_PATCH_H #define _KSPLICE_PATCH_H #define KSPLICE_OPTION_ASSUME_RODATA 0 #define KSPLICE_OPTION_MATCH_DATA_EARLY 1 struct ksplice_option { int type; const void *target; } __attribute__((packed)); #ifdef __KERNEL__ #include #include #ifndef __used #define __used __attribute_used__ #endif #define ksplice_call_int(name, fn) \ static typeof(int (*)(void)) __ksplice_##name##_##fn __used \ __attribute__((__section__(".ksplice_call_" #name))) = fn #define ksplice_call_void(name, fn) \ static typeof(void (*)(void)) __ksplice_##name##_##fn __used \ __attribute__((__section__(".ksplice_call_" #name))) = fn #define ksplice_pre_apply(fn) ksplice_call_int(pre_apply, fn) #define ksplice_check_apply(fn) ksplice_call_int(check_apply, fn) #define ksplice_apply(fn) ksplice_call_void(apply, fn) #define ksplice_post_apply(fn) ksplice_call_void(post_apply, fn) #define ksplice_fail_apply(fn) ksplice_call_void(fail_apply, fn) #define ksplice_pre_reverse(fn) ksplice_call_int(pre_reverse, fn) #define ksplice_check_reverse(fn) ksplice_call_int(check_reverse, fn) #define ksplice_reverse(fn) ksplice_call_void(reverse, fn) #define ksplice_post_reverse(fn) ksplice_call_void(post_reverse, fn) #define ksplice_fail_reverse(fn) ksplice_call_void(fail_reverse, fn) #define ksplice_assume_rodata(obj) \ ksplice_option(KSPLICE_OPTION_ASSUME_RODATA, obj) #define ksplice_match_data_early(obj) \ ksplice_option(KSPLICE_OPTION_MATCH_DATA_EARLY, obj) #if BITS_PER_LONG == 32 #define KSPLICE_PTR ".long" #elif BITS_PER_LONG == 64 #define KSPLICE_PTR ".quad" #endif /* BITS_PER_LONG */ #define ksplice_option(num, obj) \ __asm__(".pushsection \".ksplice_options\", \"a\"\n" \ "\t.long " __stringify(num) "\n" \ "\t" KSPLICE_PTR " " #obj "\n" \ ".popsection") int init_shadow_field_type(int *shadow_key, typeof(GFP_KERNEL) gfp_flags); void *init_shadow_field(int *shadow_key, void *obj, int size, typeof(GFP_KERNEL) gfp_flags); void cleanup_shadow_field(int *shadow_key, void *obj); void *get_shadow_field(int *shadow_key, void *obj); void cleanup_shadow_field_type(int *shadow_key); #define __DEFINE_SHADOW_FIELD(base_type, field_type, gfp_flags, \ init_field_type_fn, init_field_fn, get_field_fn, \ make_field_fn, cleanup_field_fn, \ cleanup_field_type_fn, shadow_key, init_field) \ static int shadow_key = 0; \ int init_field_type_fn(void) \ { \ return init_shadow_field_type(&shadow_key, gfp_flags); \ } \ field_type *init_field_fn(base_type *obj, typeof(GFP_KERNEL) flags) \ { \ field_type *data = init_shadow_field(&shadow_key, (void *)obj, \ sizeof(*data), flags); \ if (data != NULL) \ init_field(data); \ return data; \ } \ void cleanup_field_fn(base_type *obj) \ { \ cleanup_shadow_field(&shadow_key, obj); \ } \ field_type *get_field_fn(base_type *obj) \ { \ return get_shadow_field(&shadow_key, obj); \ } \ field_type *make_field_fn(base_type *obj, typeof(GFP_KERNEL) flags) \ { \ void *data = get_shadow_field(&shadow_key, (void *)obj); \ if (data == NULL) \ data = init_field_fn(obj, flags); \ return data; \ } \ void cleanup_field_type_fn(void) \ { \ return cleanup_shadow_field_type(&shadow_key); \ } \ struct eat_trailing_semicolon #define DEFINE_SHADOW_FIELD(base_type, field_type, gfp_flags, name, init_field) \ __DEFINE_SHADOW_FIELD(base_type, field_type, gfp_flags, \ init_##name##_shadows, init_##name##_shadow, \ get_##name##_shadow, make_##name##_shadow, \ cleanup_##name##_shadow, cleanup_##name##_shadows,\ shadow_key_##name, init_field); \ ksplice_check_apply(init_##name##_shadows); \ ksplice_post_reverse(cleanup_##name##_shadows); \ ksplice_fail_apply(cleanup_##name##_shadows) #define __DECLARE_SHADOW_FIELD(base_type, field_type, init_field_type_fn, \ init_field_fn, get_field_fn, make_field_fn, \ cleanup_field_fn, cleanup_field_type_fn) \ int init_field_type_fn(void); \ field_type *init_field_fn(base_type *obj, typeof(GFP_KERNEL) flags); \ void cleanup_field_fn(base_type *obj); \ field_type *get_field_fn(base_type *obj); \ field_type *make_field_fn(base_type *obj, typeof(GFP_KERNEL) flags); \ void cleanup_field_type_fn(void) #define DECLARE_SHADOW_FIELD(base_type, field_type, name) \ __DECLARE_SHADOW_FIELD(base_type, field_type, init_##name##_shadows, \ init_##name##_shadow, get_##name##_shadow, \ make_##name##_shadow, cleanup_##name##_shadow, \ cleanup_##name##_shadows) #endif /* __KERNEL__ */ #endif /* _KSPLICE_PATCH_H */ ksplice-0.9.9/ksplice-patch/ksplice-shadow.h0000644000000000000000000000334711244274432017510 0ustar rootroot#include #include #include "ksplice-patch.h" struct shadow_field { void *obj; void *data; int *key; struct list_head list; }; LIST_HEAD(shadow_list); DEFINE_SPINLOCK(shadow_lock); int init_shadow_field_type(int *shadow_key, typeof(GFP_KERNEL) gfp_flags) { return 0; } void *init_shadow_field(int *shadow_key, void *obj, int size, typeof(GFP_KERNEL) gfp_flags) { struct shadow_field *shadow = kmalloc(sizeof(*shadow), gfp_flags); if (shadow == NULL) return NULL; shadow->obj = obj; shadow->key = shadow_key; shadow->data = kmalloc(size, gfp_flags); if (shadow->data == NULL) { kfree(shadow); return NULL; } spin_lock(&shadow_lock); list_add(&shadow->list, &shadow_list); spin_unlock(&shadow_lock); return shadow->data; } void cleanup_shadow_field(int *shadow_key, void *obj) { struct shadow_field *shadow; spin_lock(&shadow_lock); list_for_each_entry(shadow, &shadow_list, list) { if (shadow->obj == obj && shadow->key == shadow_key) { list_del(&shadow->list); kfree(shadow->data); kfree(shadow); goto out; } } out: spin_unlock(&shadow_lock); } void *get_shadow_field(int *shadow_key, void *obj) { struct shadow_field *shadow; void *data = NULL; spin_lock(&shadow_lock); list_for_each_entry(shadow, &shadow_list, list) { if (shadow->obj == obj && shadow->key == shadow_key) { data = shadow->data; goto out; } } out: spin_unlock(&shadow_lock); return data; } void cleanup_shadow_field_type(int *shadow_key) { struct shadow_field *shadow, *n; spin_lock(&shadow_lock); list_for_each_entry_safe(shadow, n, &shadow_list, list) { if (shadow->key == shadow_key) { list_del(&shadow->list); kfree(shadow->data); kfree(shadow); } } spin_unlock(&shadow_lock); } ksplice-0.9.9/objmanip.c0000644000000000000000000034114411244274432013636 0ustar rootroot/* This file is based in part on objcopy.c from GNU Binutils v2.17. * * Copyright (C) 1991-2006 Free Software Foundation, Inc. * Copyright (C) 2007-2009 Ksplice, Inc. * Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA * 02110-1301, USA. */ /* objmanip performs various object file manipulations for Ksplice. Its first * two arguments are always an input object file and an output object file. * * - keep-new-code: "objmanip keep-new-code " * * This mode prepares the object file to be installed as a ksplice update. The * kid argument is the ksplice id string for the ksplice update being built. * * - keep-old-code: "objmanip keep-old-code" * * This mode prepares the object file to be used for run-pre matching. This * involves replacing all ELF relocations with ksplice relocations and * writing ksplice_section structures for each ELF text or data section. * * - rmsyms mode: "objmanip rmsyms * * In this mode, any ELF relocations involving the list of symbol names given on * standard input are replaced with ksplice relocations. This is used only * for KSPLICE_STANDALONE. * * - finalize mode: "objmanip finalize" * * In this mode, any ELF relocations to undefined symbols are replaced with * ksplice relocations. */ /* Always define KSPLICE_STANDALONE, even if you're using integrated Ksplice. objmanip won't compile without it. */ #define KSPLICE_STANDALONE #define _GNU_SOURCE #include "objcommon.h" #include "kmodsrc/ksplice.h" #include "kmodsrc/offsets.h" #include "ksplice-patch/ksplice-patch.h" #include #include #include #include #include #define KSPLICE_SYMBOL_STR "KSPLICE_SYMBOL_" #define symbol_init(sym) *(sym) = (asymbol *)NULL DEFINE_HASH_TYPE(asymbol *, symbol_hash, symbol_hash_init, symbol_hash_free, symbol_hash_lookup, symbol_init); DECLARE_VEC_TYPE(const char *, str_vec); DECLARE_VEC_TYPE(unsigned long, ulong_vec); #define bool_init(b) *(b) = false DEFINE_HASH_TYPE(bool, bool_hash, bool_hash_init, bool_hash_free, bool_hash_lookup, bool_init); #define ulong_init(x) *(x) = 0 DEFINE_HASH_TYPE(unsigned long, ulong_hash, ulong_hash_init, ulong_hash_free, ulong_hash_lookup, ulong_init); void do_keep_new_code(struct superbfd *isbfd, const char *pre); void do_keep_old_code(struct superbfd *isbfd); void do_finalize(struct superbfd *isbfd); void do_rmsyms(struct superbfd *isbfd); bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss, arelent *old_reloc, arelent *new_reloc); bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc); bool all_relocs_equal(struct span *old_span, struct span *new_span); static bool part_of_reloc(struct supersect *ss, unsigned long addr); static bool nonrelocs_equal(struct span *old_span, struct span *new_span); static void handle_section_symbol_renames(struct superbfd *oldsbfd, struct superbfd *newsbfd); static void compute_entry_points(struct superbfd *sbfd); static void copy_patched_entry_points(struct superbfd *oldsbfd, struct superbfd *newsbfd); enum supersect_type supersect_type(struct supersect *ss); void initialize_supersect_types(struct superbfd *sbfd); static void initialize_spans(struct superbfd *sbfd); static void initialize_string_spans(struct supersect *ss); static void initialize_table_spans(struct superbfd *sbfd, struct table_section *s); static void initialize_table_section_spans(struct superbfd *sbfd); static void initialize_ksplice_call_spans(struct supersect *ss); struct span *reloc_target_span(struct supersect *ss, arelent *reloc); static struct span *span_offset_target_span(struct span *span, int offset); static bfd_vma reloc_target_offset(struct supersect *ss, arelent *reloc); struct span *find_span(struct supersect *ss, bfd_size_type address); void remove_unkept_spans(struct superbfd *sbfd); void compute_span_shifts(struct superbfd *sbfd); static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size); static bool is_table_section(const char *name, bool consider_other, bool consider_crc); const struct table_section *get_table_section(const char *name); void mangle_section_name(struct superbfd *sbfd, const char *name); void rm_relocs(struct superbfd *isbfd); void rm_some_relocs(struct supersect *ss); void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc); static void write_ksplice_reloc_howto(struct supersect *ss, const struct ksplice_reloc_howto *const *addr, reloc_howto_type *howto, enum ksplice_reloc_howto_type type); static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset, const char *str, enum ksplice_reloc_howto_type type); static void write_ksplice_patch_reloc(struct supersect *ss, const char *sectname, unsigned long *addr, bfd_size_type size, const char *label, long addend); static void write_ksplice_nonreloc_howto(struct supersect *ss, const struct ksplice_reloc_howto *const *addr, enum ksplice_reloc_howto_type type, int size); static void write_date_relocs(struct superbfd *sbfd, const char *str, enum ksplice_reloc_howto_type type); static void write_table_relocs(struct superbfd *sbfd, const char *sectname, enum ksplice_reloc_howto_type type); static void write_ksplice_table_reloc(struct supersect *ss, unsigned long address, const char *label, enum ksplice_reloc_howto_type type); void load_ksplice_symbol_offsets(struct superbfd *sbfd); void write_canary(struct supersect *ss, int offset, bfd_size_type size, bfd_vma dst_mask); static void write_ksplice_section(struct span *span); void write_ksplice_patches(struct superbfd *sbfd, struct span *span); void write_ksplice_patch(struct superbfd *sbfd, struct span *span, const char *label, long offset); void *write_patch_storage(struct supersect *ss, struct ksplice_patch *patch, size_t size, struct supersect **data_ssp); void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name, const char *label, const char *sectname, long offset); static void write_bugline_patches(struct superbfd *sbfd); asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name); void filter_table_sections(struct superbfd *isbfd); void filter_table_section(struct superbfd *sbfd, const struct table_section *s); void keep_referenced_sections(struct superbfd *sbfd); void mark_precallable_spans(struct superbfd *sbfd); bfd_boolean copy_object(bfd *ibfd, bfd *obfd); void setup_section(bfd *ibfd, asection *isection, void *obfdarg); static void setup_new_section(bfd *obfd, struct supersect *ss); static void write_section(bfd *obfd, asection *osection, void *arg); static void delete_obsolete_relocs(struct supersect *ss); void mark_symbols_used_in_relocations(bfd *abfd, asection *isection, void *ignored); static void ss_mark_symbols_used_in_relocations(struct supersect *ss); void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms, struct asymbolp_vec *isyms); static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym); struct supersect *__attribute((format(printf, 2, 3))) make_section(struct superbfd *sbfd, const char *fmt, ...); void __attribute__((format(printf, 3, 4))) write_string(struct supersect *ss, const char **addr, const char *fmt, ...); void write_ksplice_export(struct superbfd *sbfd, struct span *span, bool del); void write_reloc(struct supersect *ss, const void *addr, asymbol **symp, bfd_vma offset); arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp, bfd_vma offset); static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd, void (*fn)(struct span *old_span, asymbol *oldsym, struct span *new_span, asymbol *newsym)); static void check_global_symbols(struct span *old_span, asymbol *oldsym, struct span *new_span, asymbol *newsym); static void match_global_symbols(struct span *old_span, asymbol *oldsym, struct span *new_span, asymbol *newsym); static void match_symbol_spans(struct span *old_span, asymbol *oldsym, struct span *new_span, asymbol *newsym); static void match_table_spans(struct span *old_span, struct span *new_span); static void match_other_spans(struct span *old_span, struct span *new_span); static struct span *get_crc_span(struct span *span, const struct table_section *ts); static void foreach_span_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd, void (*fn)(struct span *old_span, struct span *new_span)); static void match_spans_by_label(struct span *old_span, struct span *new_span); static void match_string_spans(struct span *old_span, struct span *new_span); static void mark_new_spans(struct superbfd *sbfd); static void handle_deleted_spans(struct superbfd *oldsbfd, struct superbfd *newsbfd); static void unmatch_addr_spans(struct span *old_span, struct span *new_span, const struct table_section *ts); static void compare_matched_spans(struct superbfd *newsbfd); static void compare_spans(struct span *old_span, struct span *new_span); static void update_nonzero_offsets(struct superbfd *sbfd); static void handle_nonzero_offset_relocs(struct supersect *ss); static void keep_span(struct span *span); static void init_objmanip_superbfd(struct superbfd *sbfd); static const char *label_lookup(struct superbfd *sbfd, asymbol *sym); static void label_map_set(struct superbfd *sbfd, const char *oldlabel, const char *label); static void print_label_changes(struct superbfd *sbfd); static void init_label_map(struct superbfd *sbfd); static void change_initial_label(struct span *span, const char *label); static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value); static void init_csyms(struct superbfd *sbfd); static void init_callers(struct superbfd *sbfd); static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym); static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym); static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym); static char *symbol_label(struct superbfd *sbfd, asymbol *sym); int verbose = 0; #define debug_(sbfd, level, fmt, ...) \ do { \ if (verbose >= (level)) \ printf("%s: " fmt, (sbfd)->abfd->filename, \ ## __VA_ARGS__); \ } while (0) #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__) #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__) #define err(sbfd, fmt, ...) \ do { \ fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \ ## __VA_ARGS__); \ } while (0) struct str_vec delsects; struct asymbolp_vec extract_syms; bool changed; struct ksplice_config *config; const char *modestr, *kid, *finalize_target = NULL; bool write_output = true; struct superbfd *offsets_sbfd = NULL; #define mode(str) strstarts(modestr, str) DECLARE_VEC_TYPE(unsigned long, addr_vec); DEFINE_HASH_TYPE(struct addr_vec, addr_vec_hash, addr_vec_hash_init, addr_vec_hash_free, addr_vec_hash_lookup, vec_init); struct addr_vec_hash system_map; struct bool_hash system_map_written; struct ulong_hash ksplice_symbol_offset; struct ulong_hash ksplice_howto_offset; struct ulong_hash ksplice_string_offset; void load_system_map() { const char *config_dir = getenv("KSPLICE_CONFIG_DIR"); assert(config_dir); FILE *fp = fopen(strprintf("%s/System.map", config_dir), "r"); assert(fp); addr_vec_hash_init(&system_map); unsigned long addr; char type; char *sym; while (fscanf(fp, "%lx %c %as\n", &addr, &type, &sym) == 3) *vec_grow(addr_vec_hash_lookup(&system_map, sym, TRUE), 1) = addr; fclose(fp); } void load_ksplice_symbol_offsets(struct superbfd *sbfd) { asection *sect = bfd_get_section_by_name(sbfd->abfd, ".ksplice_symbols"); if (sect == NULL) return; struct supersect *ss = fetch_supersect(sbfd, sect); struct ksplice_symbol *ksym; for (ksym = ss->contents.data; (void *)ksym < ss->contents.data + ss->contents.size; ksym++) { const char *label = read_string(ss, &ksym->label); unsigned long *ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE); *ksymbol_offp = addr_offset(ss, ksym); } } void load_offsets() { char *kmodsrc = getenv("KSPLICE_KMODSRC"); assert(kmodsrc != NULL); bfd *offsets_bfd = bfd_openr(strprintf("%s/offsets.o", kmodsrc), NULL); assert(offsets_bfd != NULL); char **matching; assert(bfd_check_format_matches(offsets_bfd, bfd_object, &matching)); offsets_sbfd = fetch_superbfd(offsets_bfd); asection *config_sect = bfd_get_section_by_name(offsets_sbfd->abfd, ".ksplice_config"); struct supersect *config_ss = fetch_supersect(offsets_sbfd, config_sect); config = config_ss->contents.data; } void load_options(struct superbfd *sbfd) { asection *sect = bfd_get_section_by_name(sbfd->abfd, ".ksplice_options"); if (sect == NULL) return; struct supersect *ss = fetch_supersect(sbfd, sect); const struct ksplice_option *opt; for (opt = ss->contents.data; (void *)opt < ss->contents.data + ss->contents.size; opt++) { if (opt->type == KSPLICE_OPTION_ASSUME_RODATA) { arelent *reloc = find_reloc(ss, &opt->target); assert(reloc != NULL); struct span *span = reloc_target_span(ss, reloc); assert(span != NULL); assert(span->ss->type == SS_TYPE_DATA); assert(span->start == 0 && span->size == span->ss->contents.size); span->ss->type = SS_TYPE_RODATA; } else if (opt->type == KSPLICE_OPTION_MATCH_DATA_EARLY) { arelent *reloc = find_reloc(ss, &opt->target); assert(reloc != NULL); struct span *span = reloc_target_span(ss, reloc); assert(span != NULL); assert(span->ss->type == SS_TYPE_DATA); assert(span->start == 0 && span->size == span->ss->contents.size); span->ss->match_data_early = true; } else { err(sbfd, "Unrecognized Ksplice option %d\n", opt->type); DIE; } } } bool matchable_data_section(struct supersect *ss) { if (ss->type == SS_TYPE_STRING) return true; if (ss->type == SS_TYPE_RODATA) return true; if (ss->type == SS_TYPE_DATA && ss->relocs.size != 0) return true; if (ss->type == SS_TYPE_EXPORT) return true; if (ss->type == SS_TYPE_BUGTABLE) return true; return false; } bool unchangeable_section(struct supersect *ss) { if (ss->type == SS_TYPE_DATA) return true; if (ss->type == SS_TYPE_IGNORED && !strstarts(ss->name, ".debug") && strcmp(ss->name, "__ksymtab_strings") != 0) return true; return false; } int main(int argc, char *argv[]) { if (getenv("KSPLICE_VERBOSE") != NULL) verbose = atoi(getenv("KSPLICE_VERBOSE")); bfd_init(); bfd *ibfd = bfd_openr(argv[1], NULL); assert(ibfd); char **matching; if (bfd_check_format_matches(ibfd, bfd_archive, &matching) && bfd_openr_next_archived_file(ibfd, NULL) == NULL) return 66; /* empty archive */ assert(bfd_check_format_matches(ibfd, bfd_object, &matching)); const char *output_target = bfd_get_target(ibfd); load_system_map(); load_offsets(); bool_hash_init(&system_map_written); ulong_hash_init(&ksplice_symbol_offset); ulong_hash_init(&ksplice_howto_offset); ulong_hash_init(&ksplice_string_offset); struct superbfd *isbfd = fetch_superbfd(ibfd); modestr = argv[3]; if (mode("finalize")) finalize_target = argv[4]; init_objmanip_superbfd(isbfd); if (mode("keep-new-code")) { kid = argv[5]; do_keep_new_code(isbfd, argv[4]); } else if (mode("keep-old-code")) { do_keep_old_code(isbfd); } else if (mode("finalize")) { do_finalize(isbfd); } else if (mode("rmsyms")) { do_rmsyms(isbfd); } if (write_output) { bfd *obfd = bfd_openw(argv[2], output_target); assert(obfd); copy_object(ibfd, obfd); assert(bfd_close(obfd)); } if (offsets_sbfd != NULL) assert(bfd_close(offsets_sbfd->abfd)); assert(bfd_close(ibfd)); return EXIT_SUCCESS; } void do_keep_new_code(struct superbfd *isbfd, const char *pre) { struct bfd *prebfd = bfd_openr(pre, NULL); assert(prebfd != NULL); char **matching; assert(bfd_check_format_matches(prebfd, bfd_object, &matching)); struct superbfd *presbfd = fetch_superbfd(prebfd); init_objmanip_superbfd(presbfd); foreach_symbol_pair(presbfd, isbfd, match_global_symbols); debug1(isbfd, "Matched global\n"); foreach_span_pair(presbfd, isbfd, match_string_spans); debug1(isbfd, "Matched string spans\n"); foreach_symbol_pair(presbfd, isbfd, match_symbol_spans); debug1(isbfd, "Matched by name\n"); foreach_span_pair(presbfd, isbfd, match_spans_by_label); debug1(isbfd, "Matched by label\n"); foreach_span_pair(presbfd, isbfd, match_table_spans); debug1(isbfd, "Matched table spans\n"); foreach_span_pair(presbfd, isbfd, match_other_spans); debug1(isbfd, "Matched other spans\n"); do { changed = false; compare_matched_spans(isbfd); update_nonzero_offsets(isbfd); mark_new_spans(isbfd); } while (changed); vec_init(&delsects); foreach_symbol_pair(presbfd, isbfd, check_global_symbols); handle_deleted_spans(presbfd, isbfd); handle_section_symbol_renames(presbfd, isbfd); copy_patched_entry_points(presbfd, isbfd); assert(bfd_close(prebfd)); do { changed = false; mark_precallable_spans(isbfd); } while (changed); asection *sect; for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(isbfd, sect); ss->keep = false; struct span *span; for (span = ss->spans.data; span < ss->spans.data + ss->spans.size; span++) { if (strstarts(ss->name, ".ksplice_options")) span->keep = false; else if (span->new || span->patch || span->datapatch) keep_span(span); else span->keep = false; if (span->patch && span->precallable) { err(isbfd, "Patched span %s can be reached " "by a precall function\n", span->label); DIE; } } } print_label_changes(isbfd); for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(isbfd, sect); struct span *span; for (span = ss->spans.data; span < ss->spans.data + ss->spans.size; span++) { if (span->patch || span->bugpatch || span->datapatch) debug0(isbfd, "Patching span %s\n", span->label); } } for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(isbfd, sect); struct span *span; for (span = ss->spans.data; span < ss->spans.data + ss->spans.size; span++) { if (span->new) debug0(isbfd, "New span %s\n", span->label); } } write_output = false; const char **sectname; for (sectname = delsects.data; sectname < delsects.data + delsects.size; sectname++) { write_output = true; debug0(isbfd, "Deleted section: %s\n", *sectname); } filter_table_sections(isbfd); compute_span_shifts(isbfd); for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(isbfd, sect); if (ss->type == SS_TYPE_KSPLICE_CALL) continue; struct span *span; for (span = ss->spans.data; span < ss->spans.data + ss->spans.size; span++) { if (span->keep || span->bugpatch) write_output = true; if (span->patch || span->new || span->datapatch) write_ksplice_section(span); if (span->patch || span->datapatch) write_ksplice_patches(isbfd, span); if (ss->type == SS_TYPE_EXPORT && span->new) write_ksplice_export(isbfd, span, false); } } write_bugline_patches(isbfd); rm_relocs(isbfd); remove_unkept_spans(isbfd); } void do_keep_old_code(struct superbfd *isbfd) { asection *sect; for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(isbfd, sect); ss->keep = false; struct span *span; for (span = ss->spans.data; span < ss->spans.data + ss->spans.size; span++) { span->keep = false; if (ss->type == SS_TYPE_TEXT && !strstarts(ss->name, ".fixup")) keep_span(span); if (ss->type == SS_TYPE_EXPORT) keep_span(span); } } asymbol **symp; for (symp = isbfd->syms.data; symp < isbfd->syms.data + isbfd->syms.size; symp++) { asymbol *sym = *symp; if (!bfd_is_const_section(sym->section) && (sym->flags & BSF_GLOBAL) != 0) { struct supersect *sym_ss = fetch_supersect(isbfd, sym->section); if (sym->value == sym_ss->contents.size) continue; struct span *span = find_span(sym_ss, sym->value); assert(span != NULL); if (sym_ss->type != SS_TYPE_IGNORED) keep_span(span); } } do { changed = false; keep_referenced_sections(isbfd); } while (changed); filter_table_sections(isbfd); compute_span_shifts(isbfd); for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(isbfd, sect); asymbol *sym = canonical_symbol(isbfd, sect->symbol); if (sym == NULL) continue; if ((sym->flags & BSF_WEAK) != 0) continue; if (bfd_get_section_size(sect) == 0) continue; if (!ss->keep) continue; if (ss->type != SS_TYPE_TEXT && !matchable_data_section(ss)) continue; struct span *span; for (span = ss->spans.data; span < ss->spans.data + ss->spans.size; span++) { if (span->keep) write_ksplice_section(span); } } write_table_relocs(isbfd, "__bug_table", KSPLICE_HOWTO_BUG); write_table_relocs(isbfd, "__ex_table", KSPLICE_HOWTO_EXTABLE); rm_relocs(isbfd); remove_unkept_spans(isbfd); mangle_section_name(isbfd, "__markers"); mangle_section_name(isbfd, "__tracepoints"); mangle_section_name(isbfd, "__ex_table"); for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(isbfd, sect); if (ss->type == SS_TYPE_EXPORT) mangle_section_name(isbfd, ss->name); } } void do_finalize(struct superbfd *isbfd) { load_ksplice_symbol_offsets(isbfd); asection *sect; for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(isbfd, sect); if (ss->type == SS_TYPE_EXIT) { struct span *span; for (span = ss->spans.data; span < ss->spans.data + ss->spans.size; span++) span->keep = false; ss->keep = false; } } write_date_relocs(isbfd, "<{DATE...}>", KSPLICE_HOWTO_DATE); write_date_relocs(isbfd, "<{TIME}>", KSPLICE_HOWTO_TIME); rm_relocs(isbfd); } void do_rmsyms(struct superbfd *isbfd) { asection *extract_sect = bfd_get_section_by_name(isbfd->abfd, ".ksplice_extract"); if (extract_sect != NULL) { struct supersect *extract_ss = fetch_supersect(isbfd, extract_sect); arelent **relocp; for (relocp = extract_ss->relocs.data; relocp < extract_ss->relocs.data + extract_ss->relocs.size; relocp++) { asymbol *sym = *(*relocp)->sym_ptr_ptr; if (bfd_is_und_section(sym->section)) { debug1(isbfd, "extracting symbol %s\n", sym->name); *vec_grow(&extract_syms, 1) = sym; } } } rm_relocs(isbfd); } void match_spans(struct span *old_span, struct span *new_span) { struct superbfd *sbfd = new_span->ss->parent; if (old_span->match == new_span && new_span->match == old_span) return; if (old_span->match != NULL) { err(sbfd, "Matching conflict: old %s: %s != %s\n", old_span->label, old_span->match->label, new_span->label); DIE; } if (new_span->match != NULL) { err(sbfd, "Matching conflict: new %s: %s != %s\n", new_span->label, new_span->match->label, old_span->label); DIE; } old_span->match = new_span; new_span->match = old_span; debug1(sbfd, "Matched old %s to new %s\n", old_span->label, new_span->label); if (old_span->ss->type != new_span->ss->type && old_span->ss->type == new_span->ss->orig_type) old_span->ss->type = new_span->ss->type; const struct table_section *ts = get_table_section(old_span->ss->name); if (ts == NULL || !ts->has_addr || ts->other_sect == NULL) return; struct span *old_sym_span = span_offset_target_span(old_span, ts->other_offset); struct span *new_sym_span = span_offset_target_span(new_span, ts->other_offset); assert(old_sym_span != NULL && new_sym_span != NULL); match_spans(old_sym_span, new_sym_span); } void unmatch_span(struct span *old_span) { struct span *new_span = old_span->match; old_span->match = NULL; new_span->match = NULL; new_span->bugpatch = false; if (old_span->ss->type == SS_TYPE_SPECIAL) { const struct table_section *ts = get_table_section(old_span->ss->name); if (ts != NULL && ts->has_addr) unmatch_addr_spans(old_span, new_span, ts); } new_span->patch = false; new_span->bugpatch = false; new_span->datapatch = false; changed = true; } static void match_global_symbols(struct span *old_span, asymbol *oldsym, struct span *new_span, asymbol *newsym) { if (newsym == NULL || (oldsym->flags & BSF_GLOBAL) == 0 || (newsym->flags & BSF_GLOBAL) == 0) return; match_spans(old_span, new_span); } static void check_global_symbols(struct span *old_span, asymbol *oldsym, struct span *new_span, asymbol *newsym) { if ((oldsym->flags & BSF_GLOBAL) == 0 || (newsym != NULL && (newsym->flags & BSF_GLOBAL) == 0)) return; if (old_span->ss->type == SS_TYPE_IGNORED) return; if (old_span->match != new_span) { if (new_span != NULL) err(new_span->ss->parent, "Global symbol span mismatch: %s %s/%s\n", oldsym->name, old_span->label, new_span->label); else err(old_span->ss->parent, "Global symbol span mismatch: %s %s/NULL\n", oldsym->name, old_span->label); DIE; } } static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd, void (*fn)(struct span *old_span, asymbol *oldsym, struct span *new_span, asymbol *newsym)) { asymbol **oldsymp, **newsymp; for (oldsymp = oldsbfd->syms.data; oldsymp < oldsbfd->syms.data + oldsbfd->syms.size; oldsymp++) { asymbol *oldsym = *oldsymp; if ((oldsym->flags & BSF_DEBUGGING) != 0 || bfd_is_const_section(oldsym->section)) continue; struct supersect *old_ss = fetch_supersect(oldsbfd, oldsym->section); if (old_ss->type == SS_TYPE_SPECIAL || old_ss->type == SS_TYPE_EXPORT) continue; struct span *old_span = find_span(old_ss, oldsym->value); if (old_span == NULL) { err(oldsbfd, "Could not find span for %s\n", oldsym->name); DIE; } bool found = false; for (newsymp = newsbfd->syms.data; newsymp < newsbfd->syms.data + newsbfd->syms.size; newsymp++) { asymbol *newsym = *newsymp; if ((newsym->flags & BSF_DEBUGGING) != 0 || bfd_is_const_section(newsym->section)) continue; if (strcmp(oldsym->name, newsym->name) != 0) continue; struct supersect *new_ss = fetch_supersect(newsbfd, newsym->section); if (old_ss->type != new_ss->type && old_ss->type != new_ss->orig_type) continue; assert(!found); found = true; struct span *new_span = find_span(new_ss, newsym->value); if (new_span == NULL) { err(newsbfd, "Could not find span for %s\n", newsym->name); DIE; } fn(old_span, oldsym, new_span, newsym); } if (!found) fn(old_span, oldsym, NULL, NULL); } } static void match_symbol_spans(struct span *old_span, asymbol *oldsym, struct span *new_span, asymbol *newsym) { if (newsym == NULL) return; if (old_span->ss->type == SS_TYPE_SPECIAL) return; if (static_local_symbol(old_span->ss->parent, oldsym) || static_local_symbol(new_span->ss->parent, newsym)) return; if (old_span->match == NULL && new_span->match == NULL) match_spans(old_span, new_span); } static void match_spans_by_label(struct span *old_span, struct span *new_span) { if (old_span->ss->type == SS_TYPE_STRING || (is_table_section(old_span->ss->name, true, false) && !is_table_section(old_span->ss->name, false, false))) return; if (strcmp(old_span->label, new_span->label) == 0) match_spans(old_span, new_span); } static void match_string_spans(struct span *old_span, struct span *new_span) { if (old_span->ss->type != SS_TYPE_STRING || strcmp(old_span->ss->name, new_span->ss->name) != 0) return; if (strcmp((char *)old_span->ss->contents.data + old_span->start, (char *)new_span->ss->contents.data + new_span->start) == 0) match_spans(old_span, new_span); } static void foreach_span_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd, void (*fn)(struct span *old_span, struct span *new_span)) { asection *oldsect, *newsect; struct supersect *oldss, *newss; struct span *old_span, *new_span; for (newsect = newsbfd->abfd->sections; newsect != NULL; newsect = newsect->next) { newss = fetch_supersect(newsbfd, newsect); for (oldsect = oldsbfd->abfd->sections; oldsect != NULL; oldsect = oldsect->next) { oldss = fetch_supersect(oldsbfd, oldsect); if (oldss->type != newss->type) continue; for (new_span = newss->spans.data; new_span < newss->spans.data + newss->spans.size; new_span++) { for (old_span = oldss->spans.data; old_span < oldss->spans.data + oldss->spans.size; old_span++) fn(old_span, new_span); } } } } static void mark_new_spans(struct superbfd *sbfd) { asection *sect; for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(sbfd, sect); if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_IGNORED) continue; struct span *span; for (span = ss->spans.data; span < ss->spans.data + ss->spans.size; span++) { if (span->match == NULL) span->new = true; } } } static void handle_deleted_spans(struct superbfd *oldsbfd, struct superbfd *newsbfd) { asection *sect; for (sect = oldsbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(oldsbfd, sect); struct span *span; for (span = ss->spans.data; span < ss->spans.data + ss->spans.size; span++) { if (span->match != NULL) continue; if (ss->type == SS_TYPE_EXPORT) { *vec_grow(&delsects, 1) = span->label; write_ksplice_export(newsbfd, span, true); } else if (ss->type == SS_TYPE_TEXT) { *vec_grow(&delsects, 1) = span->label; if (span->symbol == NULL) DIE; write_ksplice_deleted_patch (newsbfd, span->symbol->name, span->label, span->ss->name, 0); } } } } static void handle_nonzero_offset_relocs(struct supersect *ss) { struct span *address_span, *target_span; arelent **relocp; for (relocp = ss->relocs.data; relocp < ss->relocs.data + ss->relocs.size; relocp++) { arelent *reloc = *relocp; address_span = find_span(ss, reloc->address); if (!address_span->new && !address_span->patch) continue; asymbol *sym = *reloc->sym_ptr_ptr; if (bfd_is_const_section(sym->section)) continue; bfd_vma offset = reloc_target_offset(ss, reloc); target_span = reloc_target_span(ss, reloc); if (sym->value + offset == target_span->start) continue; if (target_span->ss->type != SS_TYPE_TEXT) continue; if (target_span->patch) continue; target_span->patch = true; changed = true; debug1(ss->parent, "Changing %s because a relocation from sect " "%s has a nonzero offset %lx+%lx into it\n", target_span->label, ss->name, (unsigned long)sym->value, (unsigned long)offset); } } static void update_nonzero_offsets(struct superbfd *sbfd) { asection *sect; for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(sbfd, sect); if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_IGNORED) continue; handle_nonzero_offset_relocs(ss); } } static void unmatch_addr_spans(struct span *old_span, struct span *new_span, const struct table_section *ts) { struct span *old_sym_span = span_offset_target_span(old_span, ts->addr_offset); struct span *new_sym_span = span_offset_target_span(new_span, ts->addr_offset); assert(old_sym_span != NULL && new_sym_span != NULL); if (old_sym_span->match == new_sym_span && new_sym_span->match == old_sym_span && !(new_sym_span->patch && new_sym_span->ss->type == SS_TYPE_TEXT)) { if (old_sym_span->ss->type == SS_TYPE_TEXT) { debug1(new_span->ss->parent, "Patching %s due " "to relocations from special section %s\n", new_sym_span->label, new_span->label); new_sym_span->patch = true; } else { debug1(new_span->ss->parent, "Unmatching %s and %s due " "to relocations from special section %s/%s\n", old_sym_span->label, new_sym_span->label, old_span->label, new_span->label); unmatch_span(old_sym_span); } changed = true; } } static void compare_spans(struct span *old_span, struct span *new_span) { struct superbfd *newsbfd = new_span->ss->parent; bool nonrelocs_match = nonrelocs_equal(old_span, new_span); bool relocs_match = all_relocs_equal(old_span, new_span); if (nonrelocs_match && relocs_match) { const struct table_section *ts = get_table_section(old_span->ss->name); if (ts != NULL && ts->crc_sect != NULL) { struct span *old_crc_span = get_crc_span(old_span, ts); struct span *new_crc_span = get_crc_span(new_span, ts); assert(old_crc_span != NULL); assert(new_crc_span != NULL); if (old_crc_span->match != new_crc_span || new_crc_span->match != old_crc_span) { debug1(newsbfd, "Unmatching %s and %s due to " "nonmatching CRCs\n", old_span->label, new_span->label); unmatch_span(old_span); } } return; } char *reason; if (new_span->contents_size != old_span->contents_size) reason = "differing sizes"; else if (!nonrelocs_match) reason = "differing contents"; else reason = "differing relocations"; if (new_span->ss->type == SS_TYPE_TEXT) { if (new_span->patch) return; new_span->patch = true; debug1(newsbfd, "Changing %s due to %s\n", new_span->label, reason); } else if (old_span->ss->type == SS_TYPE_BUGTABLE && new_span->ss->type == SS_TYPE_BUGTABLE && relocs_match) { if (new_span->bugpatch) return; debug1(newsbfd, "Changing %s due to %s\n", new_span->label, reason); new_span->bugpatch = true; } else if (new_span->ss->type == SS_TYPE_RODATA && new_span->contents_size == old_span->contents_size) { if (new_span->datapatch) return; new_span->datapatch = true; debug1(newsbfd, "Changing %s in-place due to %s\n", new_span->label, reason); } else if (new_span->ss->type == SS_TYPE_STRING && old_span->ss->type == SS_TYPE_STRING && relocs_match && strcmp(new_span->ss->contents.data + new_span->start, old_span->ss->contents.data + old_span->start) == 0) { return; } else { debug1(newsbfd, "Unmatching %s and %s due to %s\n", old_span->label, new_span->label, reason); unmatch_span(old_span); } changed = true; if (unchangeable_section(new_span->ss)) err(newsbfd, "warning: ignoring change to nonpatchable " "section %s\n", new_span->ss->name); } static void compare_matched_spans(struct superbfd *newsbfd) { asection *sect; for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(newsbfd, sect); struct span *span; for (span = ss->spans.data; span < ss->spans.data + ss->spans.size; span++) { if (span->match == NULL) continue; compare_spans(span->match, span); } } } static void handle_section_symbol_renames(struct superbfd *oldsbfd, struct superbfd *newsbfd) { asection *sect; struct span *span; for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(newsbfd, sect); for (span = ss->spans.data; span < ss->spans.data + ss->spans.size; span++) { if (span->match == NULL) continue; if (strcmp(span->label, span->match->label) == 0) continue; if (strcmp(span->orig_label, span->label) != 0 && strcmp(span->label, span->match->label) != 0) DIE; if (span->symbol != NULL) label_map_set(newsbfd, span->label, span->match->label); span->label = span->match->label; } } } static void copy_patched_entry_points(struct superbfd *oldsbfd, struct superbfd *newsbfd) { asection *sect; struct span *span; for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(newsbfd, sect); for (span = ss->spans.data; span < ss->spans.data + ss->spans.size; span++) { if (!span->patch) continue; assert(span->match != NULL); vec_init(&span->pre_entry_points); struct entry_point *entry; for (entry = span->match->entry_points.data; entry < span->match->entry_points.data + span->match->entry_points.size; entry++) { struct entry_point *e = vec_grow(&span->pre_entry_points, 1); e->name = entry->name != NULL ? strdup(entry->name) : NULL; e->label = strdup(entry->label); e->offset = entry->offset; e->symbol = NULL; } } } } static int compare_entry_points(const void *va, const void *vb) { const struct entry_point *a = va, *b = vb; if (a->offset < b->offset) return -1; else if (a->offset > b->offset) return 1; else return 0; } static void compute_entry_points(struct superbfd *sbfd) { asymbol **symp; for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size; symp++) { asymbol *sym = *symp; if (bfd_is_const_section(sym->section)) continue; struct supersect *old_ss = fetch_supersect(sbfd, sym->section); if ((sym->flags & BSF_GLOBAL) == 0) continue; struct span *span = find_span(old_ss, sym->value); struct entry_point *e = vec_grow(&span->entry_points, 1); e->label = sym->name; e->name = sym->name; e->offset = sym->value - span->start; e->symbol = sym; } asection *sect; for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(sbfd, sect); struct span *span; for (span = ss->spans.data; span < ss->spans.data + ss->spans.size; span++) { /* First make sure that 0 appears as an entry point */ bool found_zero = false; struct entry_point *entry; for (entry = span->entry_points.data; entry < span->entry_points.data + span->entry_points.size; entry++) { if (entry->offset == 0) found_zero = true; } if (!found_zero) { struct entry_point *e = vec_grow(&span->entry_points, 1); e->label = span->label; e->name = NULL; e->offset = 0; e->symbol = span->symbol; } qsort(span->entry_points.data, span->entry_points.size, sizeof(*span->entry_points.data), compare_entry_points); } } } static bool part_of_reloc(struct supersect *ss, unsigned long addr) { arelent **relocp; for (relocp = ss->relocs.data; relocp < ss->relocs.data + ss->relocs.size; relocp++) { arelent *reloc = *relocp; if (addr >= reloc->address && addr < reloc->address + bfd_get_reloc_size(reloc->howto)) return true; } return false; } static bool nonrelocs_equal(struct span *old_span, struct span *new_span) { int i; struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss; if (old_span->contents_size != new_span->contents_size) return false; const unsigned char *old = old_ss->contents.data + old_span->start; const unsigned char *new = new_ss->contents.data + new_span->start; for (i = 0; i < old_span->contents_size; i++) { if (old[i] != new[i] && !(part_of_reloc(old_ss, i + old_span->start) && part_of_reloc(new_ss, i + new_span->start))) return false; } return true; } bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss, arelent *old_reloc, arelent *new_reloc) { struct superbfd *oldsbfd = old_src_ss->parent; struct superbfd *newsbfd = new_src_ss->parent; struct span *old_addr_span = find_span(old_src_ss, old_reloc->address); struct span *new_addr_span = find_span(new_src_ss, new_reloc->address); if (old_reloc->address - old_addr_span->start != new_reloc->address - new_addr_span->start) { debug1(newsbfd, "Section %s/%s has reloc address mismatch at " "%lx\n", old_src_ss->name, new_src_ss->name, (unsigned long)old_reloc->address); return false; } if (old_reloc->howto != new_reloc->howto) { debug1(newsbfd, "Section %s/%s has howto type mismatch at " "%lx\n", old_src_ss->name, new_src_ss->name, (unsigned long)old_reloc->address); return false; } if (non_dst_mask(old_src_ss, old_reloc) != non_dst_mask(new_src_ss, new_reloc)) { debug1(newsbfd, "Section %s/%s has contents mismatch at %lx\n", old_src_ss->name, new_src_ss->name, (unsigned long)old_reloc->address); return false; } asymbol *old_sym = *old_reloc->sym_ptr_ptr; asymbol *new_sym = *new_reloc->sym_ptr_ptr; asection *old_sect = old_sym->section; asection *new_sect = new_sym->section; bfd_vma old_offset = reloc_target_offset(old_src_ss, old_reloc); bfd_vma new_offset = reloc_target_offset(new_src_ss, new_reloc); if (bfd_is_und_section(old_sect) || bfd_is_und_section(new_sect)) { if (!bfd_is_und_section(new_sect) && old_offset != 0 && fetch_supersect(newsbfd, new_sect)->type == SS_TYPE_TEXT) return false; if (!bfd_is_und_section(old_sect) && new_offset != 0 && fetch_supersect(oldsbfd, old_sect)->type == SS_TYPE_TEXT) return false; return strcmp(old_sym->name, new_sym->name) == 0 && old_offset == new_offset; } if (bfd_is_abs_section(old_sect) && bfd_is_abs_section(new_sect)) { if (old_sym->value + old_offset == new_sym->value + new_offset) return true; debug1(newsbfd, "Differing relocations from %s/%s to ABS " "section: %lx/%lx\n", old_addr_span->label, new_addr_span->label, (unsigned long)(old_sym->value + old_offset), (unsigned long)(new_sym->value + new_offset)); return false; } if (bfd_is_const_section(old_sect) || bfd_is_const_section(new_sect)) DIE; struct supersect *old_ss = fetch_supersect(oldsbfd, old_sect); struct supersect *new_ss = fetch_supersect(newsbfd, new_sect); struct span *old_span = reloc_target_span(old_src_ss, old_reloc); struct span *new_span = reloc_target_span(new_src_ss, new_reloc); if (old_span->match != new_span || new_span->match != old_span) { debug1(newsbfd, "Nonmatching relocs from %s to %s/%s\n", new_src_ss->name, old_span->label, new_span->label); return false; } if (old_sym->value + old_offset - old_span->start != new_sym->value + new_offset - new_span->start) { debug1(newsbfd, "Offsets to %s/%s differ between %s " "and %s: %lx+%lx/%lx+%lx\n", old_ss->name, new_ss->name, old_src_ss->name, new_src_ss->name, (unsigned long)old_sym->value, (unsigned long)old_offset, (unsigned long)new_sym->value, (unsigned long)new_offset); return false; } if ((old_sym->value + old_offset - old_span->start != 0 || new_sym->value + new_offset - new_span->start != 0) && new_span->patch) { debug1(newsbfd, "Relocation from %s to nonzero offsets " "%lx+%lx/%lx+%lx in changed section %s\n", new_src_ss->name, (unsigned long)old_sym->value, (unsigned long)old_offset, (unsigned long)new_sym->value, (unsigned long)new_offset, new_sym->section->name); return false; } return true; } bool all_relocs_equal(struct span *old_span, struct span *new_span) { struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss; arelent **old_relocp, **new_relocp; for (old_relocp = old_ss->relocs.data; old_relocp < old_ss->relocs.data + old_ss->relocs.size; old_relocp++) { if (find_span(old_ss, (*old_relocp)->address) == old_span) break; } for (new_relocp = new_ss->relocs.data; new_relocp < new_ss->relocs.data + new_ss->relocs.size; new_relocp++) { if (find_span(new_ss, (*new_relocp)->address) == new_span) break; } for (; old_relocp < old_ss->relocs.data + old_ss->relocs.size && find_span(old_ss, (*old_relocp)->address) == old_span && new_relocp < new_ss->relocs.data + new_ss->relocs.size && find_span(new_ss, (*new_relocp)->address) == new_span; old_relocp++, new_relocp++) { if (!relocs_equal(old_ss, new_ss, *old_relocp, *new_relocp)) return false; } if ((old_relocp < old_ss->relocs.data + old_ss->relocs.size && find_span(old_ss, (*old_relocp)->address) == old_span) || (new_relocp < new_ss->relocs.data + new_ss->relocs.size && find_span(new_ss, (*new_relocp)->address) == new_span)) { debug1(new_ss->parent, "Different reloc count between %s and " "%s\n", old_span->label, new_span->label); return false; } return true; } bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc) { int bits = bfd_get_reloc_size(reloc->howto) * 8; void *address = ss->contents.data + reloc->address; bfd_vma x = bfd_get(bits, ss->parent->abfd, address); return x & ~reloc->howto->dst_mask; } void rm_relocs(struct superbfd *isbfd) { asection *p; for (p = isbfd->abfd->sections; p != NULL; p = p->next) { struct supersect *ss = fetch_supersect(isbfd, p); bool remove_relocs = ss->keep; if (mode("keep") && ss->type == SS_TYPE_SPECIAL) remove_relocs = false; if (ss->type == SS_TYPE_KSPLICE || ss->type == SS_TYPE_KSPLICE_CALL) remove_relocs = false; if (mode("finalize") && (strstarts(ss->name, ".ksplice_patches") || strstarts(ss->name, ".ksplice_relocs"))) remove_relocs = true; if (remove_relocs) rm_some_relocs(ss); } } void rm_some_relocs(struct supersect *ss) { struct arelentp_vec orig_relocs; vec_move(&orig_relocs, &ss->relocs); arelent **relocp; for (relocp = orig_relocs.data; relocp < orig_relocs.data + orig_relocs.size; relocp++) { bool rm_reloc = false; asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr; if (mode("rmsyms") && bfd_is_und_section(sym_ptr->section)) { asymbol **esymp; for (esymp = extract_syms.data; esymp < extract_syms.data + extract_syms.size; esymp++) { if (sym_ptr == *esymp) { rm_reloc = true; break; } } } if (mode("keep")) rm_reloc = true; if (mode("keep-new-code")) { if (bfd_is_const_section(sym_ptr->section)) { rm_reloc = false; } else { bfd_vma offset = reloc_target_offset(ss, *relocp); struct span *target_span = reloc_target_span(ss, *relocp); if (target_span->new || (target_span->ss->type == SS_TYPE_TEXT && sym_ptr->value + offset != target_span->start)) rm_reloc = false; } const struct table_section *ts = get_table_section(ss->name); if (ts != NULL && ts->has_addr && ((*relocp)->address % ts->entry_size == ts->addr_offset || (*relocp)->address % ts->entry_size == ts->other_offset)) rm_reloc = false; } if (mode("finalize") && bfd_is_und_section(sym_ptr->section)) rm_reloc = true; if (strcmp(sym_ptr->name, "mcount") == 0 && bfd_is_und_section(sym_ptr->section)) rm_reloc = false; if (!find_span(ss, (*relocp)->address)->keep) rm_reloc = false; if (rm_reloc) write_ksplice_reloc(ss, *relocp); else *vec_grow(&ss->relocs, 1) = *relocp; } } struct supersect *make_section(struct superbfd *sbfd, const char *fmt, ...) { va_list ap; va_start(ap, fmt); char *name = vstrprintf(fmt, ap); va_end(ap); asection *sect = bfd_get_section_by_name(sbfd->abfd, name); if (sect != NULL) return fetch_supersect(sbfd, sect); else return new_supersect(sbfd, name); } arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp, bfd_vma offset) { bfd_reloc_code_real_type code; switch (bfd_arch_bits_per_address(ss->parent->abfd)) { case 32: code = BFD_RELOC_32; break; case 64: code = BFD_RELOC_64; break; default: DIE; } arelent *reloc = malloc(sizeof(*reloc)); reloc->sym_ptr_ptr = symp; reloc->address = addr_offset(ss, addr); reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code); reloc->addend = offset; return reloc; } void write_reloc(struct supersect *ss, const void *addr, asymbol **symp, bfd_vma offset) { *vec_grow(&ss->new_relocs, 1) = create_reloc(ss, addr, symp, offset); } void write_string(struct supersect *ss, const char **addr, const char *fmt, ...) { va_list ap; struct supersect *str_ss = make_section(ss->parent, ".ksplice_str"); char *str; va_start(ap, fmt); int len = vasprintf(&str, fmt, ap); assert(len >= 0); va_end(ap); unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str, FALSE); if (str_offp == NULL) { char *buf = sect_grow(str_ss, len + 1, char); memcpy(buf, str, len + 1); str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE); *str_offp = addr_offset(str_ss, buf); } write_reloc(ss, addr, &str_ss->symbol, *str_offp); } void lookup_system_map(struct addr_vec *addrs, const char *name, long offset) { struct addr_vec *map_addrs = addr_vec_hash_lookup(&system_map, name, FALSE); if (map_addrs == NULL) return; unsigned long *addr, *map_addr; for (map_addr = map_addrs->data; map_addr < map_addrs->data + map_addrs->size; map_addr++) { for (addr = addrs->data; addr < addrs->data + addrs->size; addr++) { if (*addr == *map_addr + offset) break; } if (addr < addrs->data + addrs->size) continue; *vec_grow(addrs, 1) = *map_addr + offset; } } void compute_system_map_array(struct superbfd *sbfd, struct addr_vec *addrs, asymbol *sym) { if (bfd_is_abs_section(sym->section)) { *vec_grow(addrs, 1) = sym->value; } else if (bfd_is_und_section(sym->section)) { lookup_system_map(addrs, sym->name, 0); } else if (!bfd_is_const_section(sym->section)) { asymbol **gsymp; for (gsymp = sbfd->syms.data; gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) { asymbol *gsym = *gsymp; if ((gsym->flags & BSF_DEBUGGING) == 0 && gsym->section == sym->section) lookup_system_map(addrs, gsym->name, sym->value - gsym->value); } } } void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym, const char *label) { bool *done = bool_hash_lookup(&system_map_written, label, TRUE); if (*done) return; *done = true; struct addr_vec addrs; vec_init(&addrs); compute_system_map_array(sbfd, &addrs, sym); if (addrs.size != 0) { struct supersect *smap_ss = make_section(sbfd, ".ksplice_system_map"); struct ksplice_system_map *smap = sect_grow(smap_ss, 1, struct ksplice_system_map); write_string(smap_ss, &smap->label, "%s", label); struct supersect *array_ss = make_section(sbfd, ".ksplice_array"); void *buf = sect_grow(array_ss, addrs.size, typeof(*addrs.data)); memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data)); smap->nr_candidates = addrs.size; write_reloc(smap_ss, &smap->candidates, &array_ss->symbol, addr_offset(array_ss, buf)); } vec_free(&addrs); } void write_ksplice_symbol_backend(struct supersect *ss, struct ksplice_symbol *const *addr, asymbol *sym, const char *label, const char *name) { struct supersect *ksymbol_ss = make_section(ss->parent, ".ksplice_symbols"); struct ksplice_symbol *ksymbol; unsigned long *ksymbol_offp; ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, FALSE); if (ksymbol_offp != NULL) { write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp); return; } ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol); ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE); *ksymbol_offp = addr_offset(ksymbol_ss, ksymbol); write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp); write_string(ksymbol_ss, &ksymbol->label, "%s", label); if (name != NULL) { write_string(ksymbol_ss, &ksymbol->name, "%s", name); write_ksplice_system_map(ksymbol_ss->parent, sym, label); } } void write_ksplice_symbol(struct supersect *ss, struct ksplice_symbol *const *addr, asymbol *sym, struct span *span, const char *addstr_sect) { const char *label, *name; if (span != NULL && span->start != 0) label = span->label; else label = label_lookup(ss->parent, sym); asymbol *gsym = canonical_symbol(ss->parent, sym); if (strcmp(addstr_sect, "") != 0) name = NULL; else if (bfd_is_und_section(sym->section)) name = sym->name; else if (bfd_is_const_section(sym->section)) name = NULL; else if (span != NULL && span->symbol == NULL) name = NULL; else if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0) name = NULL; else name = gsym->name; write_ksplice_symbol_backend(ss, addr, sym, strprintf("%s%s", addstr_sect, label), name); } void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc) { asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr; bfd_vma reloc_addend = reloc_offset(ss, orig_reloc); bfd_vma target_addend = reloc_target_offset(ss, orig_reloc); unsigned long *repladdr = ss->contents.data + orig_reloc->address; if (mode("finalize") && strstarts(ss->name, ".ksplice_patches")) { *repladdr = 0; return; } if (mode("finalize") && strstarts(ss->name, ".ksplice_relocs")) { assert(strstarts(sym_ptr->name, KSPLICE_SYMBOL_STR)); asymbol fake_sym; fake_sym.name = sym_ptr->name + strlen(KSPLICE_SYMBOL_STR); fake_sym.section = bfd_und_section_ptr; fake_sym.value = 0; fake_sym.flags = 0; write_ksplice_symbol_backend (ss, (struct ksplice_symbol **)repladdr, &fake_sym, fake_sym.name, fake_sym.name); return; } struct span *span = reloc_target_span(ss, orig_reloc); if (span == ss->spans.data && span->start != target_addend) span = NULL; write_canary(ss, orig_reloc->address, bfd_get_reloc_size(orig_reloc->howto), orig_reloc->howto->dst_mask); struct supersect *kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name); struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1, struct ksplice_reloc); struct span *address_span = find_span(ss, orig_reloc->address); write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol, orig_reloc->address + address_span->shift); if (bfd_is_und_section(sym_ptr->section) && mode("keep")) { char *name = strprintf(KSPLICE_SYMBOL_STR "%s", sym_ptr->name); asymbol **symp = make_undefined_symbolp(ss->parent, name); write_reloc(kreloc_ss, &kreloc->symbol, symp, 0); } else { write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, span, ""); } if (span != NULL && span->start != 0) { reloc_addend += sym_ptr->value - span->start; target_addend += sym_ptr->value - span->start; } kreloc->insn_addend = reloc_addend - target_addend; kreloc->target_addend = target_addend; write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, orig_reloc->howto, KSPLICE_HOWTO_RELOC); } static void write_ksplice_reloc_howto(struct supersect *ss, const struct ksplice_reloc_howto *const *addr, reloc_howto_type *howto, enum ksplice_reloc_howto_type type) { struct supersect *khowto_ss = make_section(ss->parent, ".ksplice_reloc_howtos"); struct ksplice_reloc_howto *khowto; unsigned long *khowto_offp; khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name, FALSE); if (khowto_offp != NULL) { write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp); return; } khowto = sect_grow(khowto_ss, 1, struct ksplice_reloc_howto); khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name, TRUE); *khowto_offp = addr_offset(khowto_ss, khowto); khowto->type = type; khowto->pcrel = howto->pc_relative; khowto->size = bfd_get_reloc_size(howto); khowto->dst_mask = howto->dst_mask; khowto->rightshift = howto->rightshift; khowto->signed_addend = (howto->complain_on_overflow == complain_overflow_signed) || (howto->complain_on_overflow == complain_overflow_bitfield); write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp); } #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask)) void write_canary(struct supersect *ss, int offset, bfd_size_type size, bfd_vma dst_mask) { int bits = size * 8; void *address = ss->contents.data + offset; bfd_vma x = bfd_get(bits, ss->parent->abfd, address); x = (x & ~dst_mask) | ((bfd_vma)KSPLICE_CANARY & dst_mask); bfd_put(bits, ss->parent->abfd, x, address); } static void write_date_relocs(struct superbfd *sbfd, const char *str, enum ksplice_reloc_howto_type type) { asection *sect; for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(sbfd, sect); if (ss->type != SS_TYPE_STRING && ss->type != SS_TYPE_RODATA) continue; void *ptr; struct span *span; for (span = ss->spans.data; span < ss->spans.data + ss->spans.size; span++) { if (!span->keep) continue; for (ptr = ss->contents.data + span->start; ptr + strlen(str) < ss->contents.data + span->start + span->contents_size; ptr++) { if (strcmp((const char *)ptr, str) == 0) write_ksplice_date_reloc (ss, addr_offset(ss, ptr), str, type); } } } } static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset, const char *str, enum ksplice_reloc_howto_type type) { struct supersect *kreloc_ss; kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name); struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1, struct ksplice_reloc); const char *filename = ss->parent->abfd->filename; char *c = strstr(filename, ".KSPLICE"); int flen = (c == NULL ? strlen(filename) : c - filename); write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL, strprintf("%s<%.*s>", str, flen, filename), NULL); struct span *span = find_span(ss, offset); write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol, offset + span->shift); write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type, strlen(str)); } static void write_table_relocs(struct superbfd *sbfd, const char *sectname, enum ksplice_reloc_howto_type type) { asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname); if (sect == NULL) return; struct supersect *ss = fetch_supersect(sbfd, sect); const struct table_section *s = get_table_section(sectname); if (s == NULL) DIE; void *entry; for (entry = ss->contents.data; entry < ss->contents.data + ss->contents.size; entry += s->entry_size) { struct span *span = find_span(ss, addr_offset(ss, entry)); assert(span != NULL); if (!span->keep) continue; arelent *reloc = find_reloc(ss, entry + s->addr_offset); assert(reloc != NULL); asymbol *sym = *reloc->sym_ptr_ptr; assert(!bfd_is_const_section(sym->section)); struct supersect *sym_ss = fetch_supersect(sbfd, sym->section); unsigned long addr = sym->value + reloc_target_offset(ss, reloc); write_ksplice_table_reloc(sym_ss, addr, span->label, type); } } static void write_ksplice_table_reloc(struct supersect *ss, unsigned long address, const char *label, enum ksplice_reloc_howto_type type) { struct supersect *kreloc_ss; kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name); struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1, struct ksplice_reloc); struct span *span = find_span(ss, address); assert(span != NULL); write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL, label, NULL); write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol, address + span->shift); write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type, 0); } static void write_ksplice_nonreloc_howto(struct supersect *ss, const struct ksplice_reloc_howto *const *addr, enum ksplice_reloc_howto_type type, int size) { struct supersect *khowto_ss = make_section(ss->parent, ".ksplice_reloc_howtos"); struct ksplice_reloc_howto *khowto = sect_grow(khowto_ss, 1, struct ksplice_reloc_howto); khowto->type = type; khowto->size = size; khowto->pcrel = 0; khowto->dst_mask = 0; khowto->rightshift = 0; khowto->signed_addend = 0; write_reloc(ss, addr, &khowto_ss->symbol, addr_offset(khowto_ss, khowto)); } static void write_ksplice_symbol_reloc(struct supersect *ss, const char *sectname, unsigned long *addr, asymbol *sym, const char *label, const char *name) { struct supersect *kreloc_ss; kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", sectname); struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1, struct ksplice_reloc); write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, sym, label, name); write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol, addr_offset(ss, addr)); write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, KSPLICE_HOWTO_SYMBOL, 0); } static void write_ksplice_section(struct span *span) { struct supersect *ss = span->ss; const char *sectname = span->ss->name; const struct table_section *ts = get_table_section(ss->name); if (ts != NULL && ts->has_addr) { arelent *reloc = find_reloc(ss, ss->contents.data + span->start + ts->addr_offset); assert(reloc != NULL); asymbol *rsym = *reloc->sym_ptr_ptr; assert(!bfd_is_const_section(rsym->section)); sectname = rsym->section->name; } struct supersect *ksect_ss = make_section(ss->parent, ".ksplice_sections%s", sectname); struct ksplice_section *ksect = sect_grow(ksect_ss, 1, struct ksplice_section); asymbol *sym = span->symbol == NULL ? ss->symbol : span->symbol; write_ksplice_symbol(ksect_ss, &ksect->symbol, sym, span, mode("keep-new-code") ? "(post)" : ""); ksect->size = span->size; ksect->flags = 0; if (ss->type == SS_TYPE_RODATA || ss->type == SS_TYPE_STRING || ss->type == SS_TYPE_EXPORT || ss->type == SS_TYPE_BUGTABLE) ksect->flags |= KSPLICE_SECTION_RODATA; if (ss->type == SS_TYPE_DATA) ksect->flags |= KSPLICE_SECTION_DATA; if (ss->type == SS_TYPE_TEXT) ksect->flags |= KSPLICE_SECTION_TEXT; assert(ksect->flags != 0); if (ss->type == SS_TYPE_STRING) ksect->flags |= KSPLICE_SECTION_STRING; if (ss->match_data_early) ksect->flags |= KSPLICE_SECTION_MATCH_DATA_EARLY; write_reloc(ksect_ss, &ksect->address, &ss->symbol, span->start + span->shift); if (mode("keep-old-code")) { /* Write ksplice_symbols for all the entry points */ struct entry_point *entry; for (entry = span->entry_points.data; entry < span->entry_points.data + span->entry_points.size; entry++) write_ksplice_symbol_reloc (span->ss, sectname, span->ss->contents.data + span->start + span->shift + entry->offset, entry->symbol, entry->label, entry->name); } } static void write_ksplice_patch_reloc(struct supersect *ss, const char *sectname, unsigned long *addr, bfd_size_type size, const char *label, long addend) { struct supersect *kreloc_ss; kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", sectname); struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1, struct ksplice_reloc); write_canary(ss, addr_offset(ss, addr), size, -1); write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL, label, NULL); write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol, addr_offset(ss, addr)); reloc_howto_type *howto = bfd_reloc_type_lookup(ss->parent->abfd, PASTE(BFD_RELOC_, LONG_BIT)); write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, howto, KSPLICE_HOWTO_RELOC); kreloc->target_addend = addend; kreloc->insn_addend = 0; } /* Assumes symbol is global, aka only one symbol of that name */ static asymbol *name_to_symbol(struct superbfd *sbfd, const char *name) { if (name == NULL) return NULL; asymbol **symp; for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size; symp++) { asymbol *sym = *symp; if (strcmp(name, sym->name) == 0 && ((sym->flags & BSF_GLOBAL) != 0 || bfd_is_und_section(sym->section))) return sym; } return NULL; } void write_ksplice_patches(struct superbfd *sbfd, struct span *span) { if (span->datapatch) { write_ksplice_patch(sbfd, span, span->label, 0); return; } assert(span->patch); long prev_offset = LONG_MIN; asymbol *prev_sym = NULL; const char *prev_label = NULL; struct entry_point *entry; for (entry = span->pre_entry_points.data; entry < span->pre_entry_points.data + span->pre_entry_points.size; entry++) { asymbol *sym = name_to_symbol(sbfd, entry->name); if (sym == NULL && entry->offset != 0) { /* Since it was global, name and label are the same */ write_ksplice_deleted_patch (sbfd, entry->label, entry->label, span->ss->name, entry->offset); } else if (entry->offset != prev_offset) { debug1(sbfd, "entry point: %s(%s) %lx\n", entry->label, entry->name, entry->offset); if (prev_offset + MAX_TRAMPOLINE_SIZE > entry->offset) { err(sbfd, "Overlapping trampolines: %s %lx/%lx\n", span->label, prev_offset, entry->offset); DIE; } long target_offset = 0; if (sym != NULL) target_offset = sym->value - span->start; write_ksplice_patch(sbfd, span, entry->label, target_offset); prev_offset = entry->offset; prev_sym = NULL; } if (prev_sym == NULL) { prev_sym = sym; prev_label = entry->label; } else if (sym != NULL && (prev_sym->section != sym->section || prev_sym->value != sym->value)) { err(sbfd, "Splitting global symbols in the middle of a " "span: %s+%lx != %s+%lx!\n", prev_label, (unsigned long)prev_sym->value, entry->label, (unsigned long)sym->value); DIE; } } if (prev_offset + MAX_TRAMPOLINE_SIZE > span->size) { err(sbfd, "Trampoline ends outside span: %s %lx/%lx\n", span->label, prev_offset, (unsigned long)span->size); DIE; } } void write_ksplice_patch(struct superbfd *sbfd, struct span *span, const char *label, long offset) { struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches%s", span->ss->name); struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1, struct ksplice_patch); write_ksplice_patch_reloc(kpatch_ss, span->ss->name, &kpatch->oldaddr, sizeof(kpatch->oldaddr), label, 0); if (span->ss->type == SS_TYPE_TEXT) { kpatch->type = KSPLICE_PATCH_TEXT; write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE, NULL); } else { kpatch->type = KSPLICE_PATCH_DATA; kpatch->size = span->contents_size; struct supersect *data_ss = make_section(sbfd, ".ksplice_patch_data"); write_reloc(kpatch_ss, &kpatch->contents, &span->ss->symbol, span->start + span->shift); char *saved = sect_do_grow(data_ss, 1, span->contents_size, 1); write_reloc(kpatch_ss, &kpatch->saved, &data_ss->symbol, addr_offset(data_ss, saved)); } write_reloc(kpatch_ss, &kpatch->repladdr, &span->ss->symbol, span->start + span->shift + offset); } asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name) { asymbol **symp; for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size; symp++) { asymbol *sym = *symp; if (strcmp(name, sym->name) == 0 && bfd_is_und_section(sym->section)) return symp; } asymbol ***sympp; for (sympp = sbfd->new_syms.data; sympp < sbfd->new_syms.data + sbfd->new_syms.size; sympp++) { asymbol **symp = *sympp; asymbol *sym = *symp; if (strcmp(name, sym->name) == 0 && bfd_is_und_section(sym->section)) return symp; } symp = malloc(sizeof(*symp)); *symp = bfd_make_empty_symbol(sbfd->abfd); asymbol *sym = *symp; sym->name = name; sym->section = bfd_und_section_ptr; sym->flags = 0; sym->value = 0; *vec_grow(&sbfd->new_syms, 1) = symp; return symp; } void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name, const char *label, const char *sectname, long offset) { struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches%s", sectname); struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1, struct ksplice_patch); write_ksplice_patch_reloc(kpatch_ss, sectname, &kpatch->oldaddr, sizeof(kpatch->oldaddr), label, 0); kpatch->type = KSPLICE_PATCH_TEXT; asymbol **symp = make_undefined_symbolp(sbfd, strdup(name)); write_reloc(kpatch_ss, &kpatch->repladdr, symp, offset); write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE, NULL); } void write_ksplice_export(struct superbfd *sbfd, struct span *span, bool del) { struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches"); struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1, struct ksplice_patch); struct supersect *data_ss; const struct table_section *ts = get_table_section(span->ss->name); assert(ts != NULL); const char **addr = span->ss->contents.data + span->start + ts->other_offset; const char *symname = read_string(span->ss, addr); char *oldname, *newname; if (del) { oldname = strprintf("%s:%s", span->ss->name, symname); newname = strprintf("DISABLED_%s_%s", symname, kid); } else { oldname = strprintf("%s:DISABLED_%s_%s", span->ss->name, symname, kid); newname = strprintf("%s", symname); write_string(span->ss, addr, "DISABLED_%s_%s", symname, kid); } write_ksplice_patch_reloc(kpatch_ss, "", &kpatch->oldaddr, sizeof(kpatch->oldaddr), oldname, ts->other_offset); kpatch->type = KSPLICE_PATCH_EXPORT; const char **namep = write_patch_storage(kpatch_ss, kpatch, sizeof(newname), &data_ss); write_string(data_ss, namep, "%s", newname); } void filter_table_sections(struct superbfd *isbfd) { struct supersect *tables_ss = fetch_supersect(offsets_sbfd, bfd_get_section_by_name(offsets_sbfd->abfd, ".ksplice_table_sections")); const struct table_section *ts; for (ts = tables_ss->contents.data; (void *)ts < tables_ss->contents.data + tables_ss->contents.size; ts++) { struct table_section s = *ts; s.sect = read_string(tables_ss, &ts->sect); s.other_sect = read_string(tables_ss, &ts->other_sect); s.crc_sect = read_string(tables_ss, &ts->crc_sect); filter_table_section(isbfd, &s); } } void filter_table_section(struct superbfd *sbfd, const struct table_section *s) { asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect); if (isection == NULL) return; struct supersect *ss = fetch_supersect(sbfd, isection); void *entry; for (entry = ss->contents.data; entry < ss->contents.data + ss->contents.size; entry += s->entry_size) { struct span *span = find_span(ss, addr_offset(ss, entry)); assert(span != NULL); if (s->has_addr) { struct span *sym_span = span_offset_target_span(span, s->addr_offset); assert(sym_span != NULL); if (sym_span->keep) keep_span(span); } if (s->other_sect != NULL) { struct span *sym_span = span_offset_target_span(span, s->other_offset); assert(sym_span != NULL); if (span->keep) keep_span(sym_span); } if (s->crc_sect != NULL) { struct span *crc_span = get_crc_span(span, s); assert(crc_span != NULL); if (span->keep && mode("keep-new-code")) keep_span(crc_span); } } } static void match_other_spans(struct span *old_span, struct span *new_span) { const struct table_section *ts = get_table_section(old_span->ss->name); if (ts == NULL) return; if (old_span->match == new_span && new_span->match == old_span && ts->other_sect != NULL) { void *old_entry = old_span->ss->contents.data + old_span->start; void *new_entry = new_span->ss->contents.data + new_span->start; arelent *old_reloc = find_reloc(old_span->ss, old_entry + ts->other_offset); arelent *new_reloc = find_reloc(new_span->ss, new_entry + ts->other_offset); assert(old_reloc != NULL && new_reloc != NULL); struct span *old_other_span = reloc_target_span(old_span->ss, old_reloc); struct span *new_other_span = reloc_target_span(new_span->ss, new_reloc); assert(old_other_span != NULL && new_other_span != NULL); match_spans(old_other_span, new_other_span); } } static void match_table_spans(struct span *old_span, struct span *new_span) { const struct table_section *ts = get_table_section(old_span->ss->name); if (strcmp(old_span->ss->name, new_span->ss->name) != 0) return; if (ts == NULL || old_span->ss->type != SS_TYPE_SPECIAL || new_span->ss->type != SS_TYPE_SPECIAL) return; if (old_span->match != NULL || new_span->match != NULL) return; if (ts->has_addr) { void *old_entry = old_span->ss->contents.data + old_span->start; void *new_entry = new_span->ss->contents.data + new_span->start; arelent *old_reloc = find_reloc(old_span->ss, old_entry + ts->addr_offset); arelent *new_reloc = find_reloc(new_span->ss, new_entry + ts->addr_offset); assert(old_reloc != NULL && new_reloc != NULL); struct span *old_sym_span = reloc_target_span(old_span->ss, old_reloc); struct span *new_sym_span = reloc_target_span(new_span->ss, new_reloc); assert(old_sym_span != NULL && new_sym_span != NULL); if (old_sym_span->match == new_sym_span && new_sym_span->match == old_sym_span && old_reloc->address - old_sym_span->start == new_reloc->address - new_sym_span->start) match_spans(old_span, new_span); } } static struct span *get_crc_span(struct span *span, const struct table_section *ts) { void *entry = span->ss->contents.data + span->start; asection *crc_sect = bfd_get_section_by_name(span->ss->parent->abfd, ts->crc_sect); if (crc_sect == NULL) return NULL; struct supersect *crc_ss = fetch_supersect(span->ss->parent, crc_sect); if (crc_ss == NULL) return NULL; struct span *crc_span = find_span(crc_ss, addr_offset(span->ss, entry) / ts->entry_size * ts->crc_size); return crc_span; } void mark_precallable_spans(struct superbfd *sbfd) { asection *sect; struct supersect *ss, *sym_ss; struct span *address_span, *target_span; for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) { ss = fetch_supersect(sbfd, sect); arelent **relocp; if (ss->type == SS_TYPE_SPECIAL) continue; for (relocp = ss->relocs.data; relocp < ss->relocs.data + ss->relocs.size; relocp++) { asymbol *sym = *(*relocp)->sym_ptr_ptr; address_span = find_span(ss, (*relocp)->address); if (!address_span->precallable) continue; target_span = reloc_target_span(ss, *relocp); if (target_span == NULL || target_span->keep) continue; sym_ss = fetch_supersect(sbfd, sym->section); if (sym_ss->type == SS_TYPE_IGNORED) continue; target_span->precallable = true; changed = true; } } } void keep_referenced_sections(struct superbfd *sbfd) { asection *sect; struct supersect *ss, *sym_ss; struct span *address_span, *target_span; for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) { ss = fetch_supersect(sbfd, sect); arelent **relocp; if (ss->type == SS_TYPE_SPECIAL) continue; for (relocp = ss->relocs.data; relocp < ss->relocs.data + ss->relocs.size; relocp++) { asymbol *sym = *(*relocp)->sym_ptr_ptr; address_span = find_span(ss, (*relocp)->address); if (!address_span->keep) continue; target_span = reloc_target_span(ss, *relocp); if (target_span == NULL || target_span->keep) continue; sym_ss = fetch_supersect(sbfd, sym->section); if (sym_ss->type == SS_TYPE_IGNORED) continue; keep_span(target_span); changed = true; } } } void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms) { asymbol ***sympp; for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++) *vec_grow(osyms, 1) = **sympp; } /* Modified function from GNU Binutils objcopy.c */ bfd_boolean copy_object(bfd *ibfd, bfd *obfd) { assert(bfd_set_format(obfd, bfd_get_format(ibfd))); bfd_vma start = bfd_get_start_address(ibfd); flagword flags = bfd_get_file_flags(ibfd); flags &= bfd_applicable_file_flags(obfd); assert(bfd_set_start_address(obfd, start) && bfd_set_file_flags(obfd, flags)); enum bfd_architecture iarch = bfd_get_arch(ibfd); unsigned int imach = bfd_get_mach(ibfd); assert(bfd_set_arch_mach(obfd, iarch, imach)); assert(bfd_set_format(obfd, bfd_get_format(ibfd))); /* BFD mandates that all output sections be created and sizes set before any output is done. Thus, we traverse all sections multiple times. */ bfd_map_over_sections(ibfd, setup_section, obfd); struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects; struct supersect *ss; for (ss = new_supersects; ss != NULL; ss = ss->next) setup_new_section(obfd, ss); /* Mark symbols used in output relocations so that they are kept, even if they are local labels or static symbols. Note we iterate over the input sections examining their relocations since the relocations for the output sections haven't been set yet. mark_symbols_used_in_relocations will ignore input sections which have no corresponding output section. */ bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL); for (ss = new_supersects; ss != NULL; ss = ss->next) ss_mark_symbols_used_in_relocations(ss); struct asymbolp_vec osyms; vec_init(&osyms); filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms); copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms); bfd_set_symtab(obfd, osyms.data, osyms.size); /* This has to happen after the symbol table has been set. */ bfd_map_over_sections(obfd, write_section, NULL); /* Allow the BFD backend to copy any private data it understands from the input BFD to the output BFD. This is done last to permit the routine to look at the filtered symbol table, which is important for the ECOFF code at least. */ assert(bfd_copy_private_bfd_data(ibfd, obfd)); return TRUE; } /* Modified function from GNU Binutils objcopy.c */ void setup_section(bfd *ibfd, asection *isection, void *obfdarg) { struct superbfd *isbfd = fetch_superbfd(ibfd); struct supersect *ss = fetch_supersect(isbfd, isection); bfd *obfd = obfdarg; bfd_vma vma; if (!ss->keep) return; asection *osection = bfd_make_section_anyway(obfd, ss->name); assert(osection != NULL); osection->userdata = ss; bfd_set_section_flags(obfd, osection, ss->flags); ss->symbol = osection->symbol; assert(bfd_set_section_size(obfd, osection, ss->contents.size)); vma = bfd_section_vma(ibfd, isection); assert(bfd_set_section_vma(obfd, osection, vma)); osection->lma = isection->lma; assert(bfd_set_section_alignment(obfd, osection, ss->alignment)); osection->entsize = ss->entsize; osection->output_section = osection; osection->output_offset = 0; isection->output_section = osection; isection->output_offset = 0; return; } void setup_new_section(bfd *obfd, struct supersect *ss) { asection *osection = bfd_make_section_anyway(obfd, ss->name); assert(osection != NULL); bfd_set_section_flags(obfd, osection, ss->flags); osection->userdata = ss; ss->symbol = osection->symbol; assert(bfd_set_section_size(obfd, osection, ss->contents.size)); assert(bfd_set_section_vma(obfd, osection, 0)); osection->lma = 0; assert(bfd_set_section_alignment(obfd, osection, ss->alignment)); osection->entsize = ss->entsize; osection->output_section = osection; osection->output_offset = 0; } static int compare_reloc_addresses(const void *aptr, const void *bptr) { const arelent *const *a = aptr, *const *b = bptr; return (*a)->address - (*b)->address; } static void delete_obsolete_relocs(struct supersect *ss) { if (ss->new_relocs.size == 0) return; qsort(ss->relocs.data, ss->relocs.size, sizeof(*ss->relocs.data), compare_reloc_addresses); qsort(ss->new_relocs.data, ss->new_relocs.size, sizeof(*ss->new_relocs.data), compare_reloc_addresses); struct arelentp_vec orig_relocs; vec_move(&orig_relocs, &ss->relocs); arelent **relocp, **new_relocp = ss->new_relocs.data; for (relocp = orig_relocs.data; relocp < orig_relocs.data + orig_relocs.size; relocp++) { while (new_relocp < ss->new_relocs.data + ss->new_relocs.size && (*new_relocp)->address < (*relocp)->address) new_relocp++; arelent *reloc = *relocp, *new_reloc = *new_relocp; if (new_relocp == ss->new_relocs.data + ss->new_relocs.size || reloc->address != new_reloc->address) *vec_grow(&ss->relocs, 1) = reloc; } } void write_section(bfd *obfd, asection *osection, void *arg) { struct supersect *ss = osection->userdata; if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0) return; delete_obsolete_relocs(ss); arelent **relocp; char *error_message; for (relocp = ss->new_relocs.data; relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) { bfd_vma val; if (bfd_get_arch(obfd) == bfd_arch_arm) val = osection->use_rela_p ? 0 : (*relocp)->addend; else val = 0; bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val, ss->contents.data + (*relocp)->address); if (bfd_install_relocation(obfd, *relocp, ss->contents.data, 0, osection, &error_message) != bfd_reloc_ok) { err(ss->parent, "ksplice: error installing reloc: %s", error_message); DIE; } if (mode("finalize")) { /* Check that all our sections will be allocated */ asymbol *sym = *((*relocp)->sym_ptr_ptr); if (!bfd_is_const_section(sym->section)) { struct supersect *sym_ss = fetch_supersect(ss->parent, sym->section); assert((sym_ss->flags & SEC_ALLOC) != 0); } } } memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data, ss->new_relocs.size * sizeof(*ss->new_relocs.data)); bfd_set_reloc(obfd, osection, ss->relocs.size == 0 ? NULL : ss->relocs.data, ss->relocs.size); if (ss->flags & SEC_HAS_CONTENTS) assert(bfd_set_section_contents (obfd, osection, ss->contents.data, 0, ss->contents.size)); } /* Modified function from GNU Binutils objcopy.c * * Mark all the symbols which will be used in output relocations with * the BSF_KEEP flag so that those symbols will not be stripped. * * Ignore relocations which will not appear in the output file. */ void mark_symbols_used_in_relocations(bfd *abfd, asection *isection, void *ignored) { struct superbfd *sbfd = fetch_superbfd(abfd); if (isection->output_section == NULL) return; struct supersect *ss = fetch_supersect(sbfd, isection); ss_mark_symbols_used_in_relocations(ss); } void ss_mark_symbols_used_in_relocations(struct supersect *ss) { /* Examine each symbol used in a relocation. If it's not one of the special bfd section symbols, then mark it with BSF_KEEP. */ arelent **relocp; for (relocp = ss->relocs.data; relocp < ss->relocs.data + ss->relocs.size; relocp++) { asymbol *sym = *(*relocp)->sym_ptr_ptr; if (!(bfd_is_const_section(sym->section) && sym == sym->section->symbol)) sym->flags |= BSF_KEEP; } for (relocp = ss->new_relocs.data; relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) { asymbol *sym = *(*relocp)->sym_ptr_ptr; if (!(bfd_is_const_section(sym->section) && sym == sym->section->symbol)) sym->flags |= BSF_KEEP; } } static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym) { struct superbfd *sbfd = fetch_superbfd(abfd); if (bfd_is_const_section(sym->section)) return false; struct supersect *ss = fetch_supersect(sbfd, sym->section); asymbol **symp; for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) { if (sym == *symp) break; } return symp >= ss->syms.data + ss->syms.size && (sym->flags & BSF_SECTION_SYM) == 0; } void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms, struct asymbolp_vec *isyms) { asymbol **symp; struct superbfd *sbfd = fetch_superbfd(ibfd); for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) { asymbol *sym = *symp; struct supersect *sym_ss = NULL; struct span *sym_span = NULL; if (!bfd_is_const_section(sym->section)) { sym_ss = fetch_supersect(sbfd, sym->section); sym_span = find_span(sym_ss, sym->value); } if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 && !(mode("keep-new-code") && sym_span != NULL && sym_span->new)) sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL; if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0) sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL; bool keep = bfd_is_const_section(sym->section) || (sym_ss->keep && (sym->flags & BSF_SECTION_SYM) != 0) || (sym_span != NULL && sym_span->keep); if (bfd_is_und_section(sym->section) && (sym->flags & BSF_KEEP) == 0) keep = false; if (bfd_is_abs_section(sym->section) && (sym->flags & BSF_KEEP) == 0 && (sym->flags & BSF_FILE) == 0) keep = false; if (deleted_table_section_symbol(ibfd, sym)) keep = false; if (mode("keep-old-code") && sym_ss != NULL && sym_ss->type == SS_TYPE_EXPORT) keep = false; if (keep) { if (sym_ss != NULL && !sym_ss->keep) { err(sbfd, "Kept symbol %s in unkept section " "%s\n", sym->name, sym->section->name); DIE; } *vec_grow(osyms, 1) = sym; } } } static bool is_table_section(const char *name, bool consider_other, bool consider_crc) { struct supersect *tables_ss = fetch_supersect(offsets_sbfd, bfd_get_section_by_name(offsets_sbfd->abfd, ".ksplice_table_sections")); const struct table_section *ts; for (ts = tables_ss->contents.data; (void *)ts < tables_ss->contents.data + tables_ss->contents.size; ts++) { if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0) return true; const char *osect_name = read_string(tables_ss, &ts->other_sect); if (consider_other && osect_name != NULL && strcmp(name, osect_name) == 0) return true; const char *crc_name = read_string(tables_ss, &ts->crc_sect); if (consider_crc && crc_name != NULL && strcmp(name, crc_name) == 0) return true; } return false; } const struct table_section *get_table_section(const char *name) { struct supersect *tables_ss = fetch_supersect(offsets_sbfd, bfd_get_section_by_name(offsets_sbfd->abfd, ".ksplice_table_sections")); const struct table_section *ts; for (ts = tables_ss->contents.data; (void *)ts < tables_ss->contents.data + tables_ss->contents.size; ts++) { if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0) { if (ts->entry_contents_size != 0) assert(align(ts->entry_contents_size, ts->entry_align) == ts->entry_size); struct table_section *ns = malloc(sizeof(*ns)); *ns = *ts; ns->sect = read_string(tables_ss, &ts->sect); ns->crc_sect = read_string(tables_ss, &ts->crc_sect); ns->other_sect = read_string(tables_ss, &ts->other_sect); return ns; } } return NULL; } enum supersect_type supersect_type(struct supersect *ss) { if (mode("finalize") && strcmp(finalize_target, "vmlinux") == 0 && (strstarts(ss->name, ".ksplice_relocs.exit") || strstarts(ss->name, ".ksplice_sections.exit") || strstarts(ss->name, ".ksplice_patches.exit"))) return SS_TYPE_EXIT; if (strstarts(ss->name, ".ksplice_call")) return SS_TYPE_KSPLICE_CALL; if (strstarts(ss->name, ".ksplice_extract")) return SS_TYPE_KSPLICE_EXTRACT; if (strstarts(ss->name, ".ksplice_options")) return SS_TYPE_SPECIAL; if (strstarts(ss->name, ".ksplice")) return SS_TYPE_KSPLICE; if (strstarts(ss->name, ".init")) return SS_TYPE_IGNORED; if (strstarts(ss->name, ".security_initcall.init")) return SS_TYPE_IGNORED; if (strstarts(ss->name, ".con_initcall.init")) return SS_TYPE_IGNORED; if (strstarts(ss->name, ".x86cpuvendor.init")) return SS_TYPE_IGNORED; if (strstarts(ss->name, ".early_param.init")) return SS_TYPE_IGNORED; if (strstarts(ss->name, ".taglist.init")) return SS_TYPE_IGNORED; if (strstarts(ss->name, ".x86_cpu_dev.init")) return SS_TYPE_IGNORED; if (strstarts(ss->name, ".arch.info.init")) return SS_TYPE_IGNORED; if (strstarts(ss->name, ".proc.info.init")) return SS_TYPE_IGNORED; /* .pci_fixup_* sections really should be treated as global rodata referenced only from quirks.c */ if (strstarts(ss->name, ".pci_fixup_")) return SS_TYPE_IGNORED; /* .builtin_fw sections are similar to .pci_fixup */ if (strstarts(ss->name, ".builtin_fw")) return SS_TYPE_IGNORED; /* same for .tracedata */ if (strstarts(ss->name, ".tracedata")) return SS_TYPE_IGNORED; if (strstarts(ss->name, ".debug")) return SS_TYPE_IGNORED; /* .eh_frame should probably be discarded, not ignored */ if (strstarts(ss->name, ".eh_frame")) return SS_TYPE_IGNORED; if (config->ignore_devinit && strstarts(ss->name, ".devinit")) return SS_TYPE_IGNORED; if (config->ignore_meminit && strstarts(ss->name, ".meminit")) return SS_TYPE_IGNORED; if (config->ignore_cpuinit && strstarts(ss->name, ".cpuinit")) return SS_TYPE_IGNORED; if (config->ignore_devinit && strstarts(ss->name, ".devexit")) return SS_TYPE_IGNORED; if (config->ignore_meminit && strstarts(ss->name, ".memexit")) return SS_TYPE_IGNORED; if (config->ignore_cpuinit && strstarts(ss->name, ".cpuexit")) return SS_TYPE_IGNORED; if (strstarts(ss->name, ".vgetcpu_mode") || strstarts(ss->name, ".jiffies") || strstarts(ss->name, ".wall_jiffies") || strstarts(ss->name, ".vxtime") || strstarts(ss->name, ".sys_tz") || strstarts(ss->name, ".sysctl_vsyscall") || strstarts(ss->name, ".xtime") || strstarts(ss->name, ".xtime_lock") || strstarts(ss->name, ".vsyscall")) return SS_TYPE_IGNORED; if (strstarts(ss->name, ".vdso")) return SS_TYPE_IGNORED; if (strstarts(ss->name, ".exit.text")) return SS_TYPE_TEXT; if (strstarts(ss->name, ".exit.data")) return SS_TYPE_DATA; if (strstarts(ss->name, ".text") || strstarts(ss->name, ".kernel.text") || strstarts(ss->name, ".devinit.text") || strstarts(ss->name, ".meminit.text") || strstarts(ss->name, ".cpuinit.text") || strstarts(ss->name, ".devexit.text") || strstarts(ss->name, ".memexit.text") || strstarts(ss->name, ".cpuexit.text") || strstarts(ss->name, ".ref.text") || strstarts(ss->name, ".spinlock.text") || strstarts(ss->name, ".kprobes.text") || strstarts(ss->name, ".sched.text") || strstarts(ss->name, ".entry.text") || /* OpenVZ */ (mode("keep-old-code") && strstarts(ss->name, ".fixup"))) return SS_TYPE_TEXT; int n = -1; if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 && n == strlen(ss->name)) return ss->entsize == 1 ? SS_TYPE_STRING : SS_TYPE_RODATA; if (strstarts(ss->name, ".rodata") || strstarts(ss->name, ".kernel.rodata") || strstarts(ss->name, ".devinit.rodata") || strstarts(ss->name, ".meminit.rodata") || strstarts(ss->name, ".cpuinit.rodata") || strstarts(ss->name, ".devexit.rodata") || strstarts(ss->name, ".memexit.rodata") || strstarts(ss->name, ".cpuexit.rodata") || strstarts(ss->name, ".ref.rodata") || strstarts(ss->name, "__tracepoints_strings") || strstarts(ss->name, "__markers_strings") || (mode("keep-old-code") && strstarts(ss->name, "__ex_table"))) return SS_TYPE_RODATA; if (strstarts(ss->name, ".bss")) return SS_TYPE_DATA; /* Ignore .data.percpu sections */ if (strstarts(ss->name, ".data.percpu") || strstarts(ss->name, ".kernel.data.percpu") || strstarts(ss->name, ".data..percpu")) return SS_TYPE_IGNORED; if (strstarts(ss->name, ".data") || strstarts(ss->name, ".kernel.data") || strstarts(ss->name, ".devinit.data") || strstarts(ss->name, ".cpuinit.data") || strstarts(ss->name, ".meminit.data") || strstarts(ss->name, ".devexit.data") || strstarts(ss->name, ".memexit.data") || strstarts(ss->name, ".cpuexit.data") || strstarts(ss->name, ".ref.data") || strstarts(ss->name, "__tracepoints") || strstarts(ss->name, "__markers")) return SS_TYPE_DATA; /* We replace all the ksymtab strings, so delete them */ if (strcmp(ss->name, "__ksymtab_strings") == 0) return SS_TYPE_STRING; if (strstarts(ss->name, "__ksymtab")) return SS_TYPE_EXPORT; if (strstarts(ss->name, "__bug_table")) return SS_TYPE_BUGTABLE; if (is_table_section(ss->name, true, true)) return SS_TYPE_SPECIAL; if (strstarts(ss->name, ".ARM.")) return SS_TYPE_SPECIAL; if (strstarts(ss->name, ".note")) return SS_TYPE_IGNORED; if (strstarts(ss->name, ".comment")) return SS_TYPE_IGNORED; if (strstarts(ss->name, "__param")) return SS_TYPE_IGNORED; if (strstarts(ss->name, "__obsparm")) return SS_TYPE_IGNORED; if (strstarts(ss->name, ".exitcall.exit")) return SS_TYPE_IGNORED; if (strstarts(ss->name, ".modinfo")) return SS_TYPE_IGNORED; return SS_TYPE_UNKNOWN; } void initialize_supersect_types(struct superbfd *sbfd) { asection *sect; for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(sbfd, sect); ss->type = supersect_type(ss); ss->orig_type = ss->type; if (ss->type == SS_TYPE_UNKNOWN) { err(sbfd, "Unknown section type: %s\n", ss->name); DIE; } } } static void init_label_map(struct superbfd *sbfd) { struct label_map *map; vec_init(&sbfd->maps); init_csyms(sbfd); init_callers(sbfd); struct symbol_hash csyms; symbol_hash_init(&csyms); asymbol **symp; for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size; symp++) { asymbol *csym = canonical_symbol(sbfd, *symp); if (csym == NULL) continue; char *key = strprintf("%p", csym); asymbol **csymp = symbol_hash_lookup(&csyms, key, TRUE); free(key); if (*csymp != NULL) continue; *csymp = csym; map = vec_grow(&sbfd->maps, 1); map->csym = csym; map->count = 0; map->label = symbol_label(sbfd, csym); } struct label_mapp_hash label_maps; label_mapp_hash_init(&label_maps); for (map = sbfd->maps.data; map < sbfd->maps.data + sbfd->maps.size; map++) { struct label_map **mapp = label_mapp_hash_lookup(&label_maps, map->label, TRUE); if (*mapp == NULL) { *mapp = map; continue; } struct label_map *first_map = *mapp; if (first_map->count == 0) first_map->label = strprintf("%s~%d", map->label, 0); map->label = strprintf("%s~%d", map->label, ++first_map->count); } label_mapp_hash_init(&sbfd->maps_hash); for (map = sbfd->maps.data; map < sbfd->maps.data + sbfd->maps.size; map++) { char *key = strprintf("%p", map->csym); struct label_map **mapp = label_mapp_hash_lookup(&sbfd->maps_hash, key, TRUE); free(key); *mapp = map; map->orig_label = map->label; } } static const char *label_lookup(struct superbfd *sbfd, asymbol *sym) { asymbol *csym = canonical_symbol(sbfd, sym); char *key = strprintf("%p", csym); struct label_map **mapp = label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE); free(key); if (mapp == NULL) DIE; return (*mapp)->label; } static void print_label_changes(struct superbfd *sbfd) { asection *sect; struct span *span; for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(sbfd, sect); for (span = ss->spans.data; span < ss->spans.data + ss->spans.size; span++) { if (strcmp(span->label, span->orig_label) != 0) debug1(sbfd, "Label change: %s -> %s\n", span->label, span->orig_label); } } } static void label_map_set(struct superbfd *sbfd, const char *oldlabel, const char *label) { struct label_map *map; for (map = sbfd->maps.data; map < sbfd->maps.data + sbfd->maps.size; map++) { if (strcmp(map->orig_label, oldlabel) == 0) { if (strcmp(map->orig_label, map->label) != 0 && strcmp(map->label, label) != 0) DIE; map->label = label; return; } } DIE; } static void change_initial_label(struct span *span, const char *label) { struct superbfd *sbfd = span->ss->parent; span->label = label; span->orig_label = label; if (span->symbol) { asymbol *csym = canonical_symbol(sbfd, span->symbol); char *key = strprintf("%p", csym); struct label_map **mapp = label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE); free(key); assert(mapp); (*mapp)->label = span->label; (*mapp)->orig_label = span->orig_label; span->symbol = NULL; } } static void init_callers(struct superbfd *sbfd) { string_hash_init(&sbfd->callers); asection *sect; for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(sbfd, sect); arelent **relocp; for (relocp = ss->relocs.data; relocp < ss->relocs.data + ss->relocs.size; relocp++) { asymbol *sym = *(*relocp)->sym_ptr_ptr; unsigned long val = sym->value + reloc_target_offset(ss, *relocp); char *key = strprintf("%s+%lx", sym->section->name, val); const char **ret = string_hash_lookup(&sbfd->callers, key, TRUE); free(key); asymbol *csym = canonical_symbol(sbfd, sect->symbol); if (*ret != NULL) *ret = "*multiple_callers*"; else if (static_local_symbol(sbfd, csym)) *ret = static_local_symbol(sbfd, csym); else *ret = sect->name; } } } static const char *find_caller(struct supersect *ss, asymbol *sym) { char *key = strprintf("%s+%lx", sym->section->name, (unsigned long)sym->value); const char **ret = string_hash_lookup(&ss->parent->callers, key, FALSE); free(key); if (ret == NULL) return "*no_caller*"; return *ret; } static void init_csyms(struct superbfd *sbfd) { asymbolpp_hash_init(&sbfd->csyms); asymbol **symp; for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size; symp++) { asymbol *sym = *symp; if ((sym->flags & BSF_DEBUGGING) != 0) continue; char *key = strprintf("%s+%lx", sym->section->name, (unsigned long)sym->value); asymbol ***csympp = asymbolpp_hash_lookup(&sbfd->csyms, key, TRUE); free(key); if (*csympp == NULL) { *csympp = symp; continue; } asymbol *csym = **csympp; if ((csym->flags & BSF_GLOBAL) != 0) continue; if ((sym->flags & BSF_GLOBAL) != 0) *csympp = symp; } } static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value) { char *key = strprintf("%s+%lx", ss->name, (unsigned long)value); asymbol ***csympp = asymbolpp_hash_lookup(&ss->parent->csyms, key, FALSE); free(key); if (csympp != NULL) return *csympp; /* For section symbols of sections containing no symbols, return the section symbol that relocations are generated against */ if (value == 0) return &ss->symbol; return NULL; } static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym) { if (bfd_is_const_section(sym->section)) { asymbol **csymp; for (csymp = sbfd->syms.data; csymp < sbfd->syms.data + sbfd->syms.size; csymp++) { if (sym == *csymp) return csymp; } return NULL; } return symbolp_scan(fetch_supersect(sbfd, sym->section), sym->value); } static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym) { if (bfd_is_const_section(sym->section)) return sym; asymbol **symp = canonical_symbolp(sbfd, sym); return symp != NULL ? *symp : NULL; } static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym) { struct supersect *ss = fetch_supersect(sbfd, sym->section); if ((sym->flags & BSF_LOCAL) == 0 || (sym->flags & BSF_OBJECT) == 0) return NULL; char *dot = strrchr(sym->name, '.'); if (dot == NULL || dot[1 + strspn(dot + 1, "0123546789")] != '\0') return NULL; char *basename = strndup(sym->name, dot - sym->name); /* Handle C.123.12345 symbols */ dot = strrchr(basename, '.'); if (dot != NULL && dot[1 + strspn(dot + 1, "0123546789")] == '\0') basename = strndup(basename, dot - basename); const char *caller; if (strcmp(basename, "__func__") == 0 || strcmp(basename, "__PRETTY_FUNCTION__") == 0) caller = (const char *)ss->contents.data + sym->value; else caller = find_caller(ss, sym); return strprintf("%s<%s>", basename, caller); } static char *symbol_label(struct superbfd *sbfd, asymbol *sym) { const char *filename = sbfd->abfd->filename; char *c = strstr(filename, ".KSPLICE"); int flen = (c == NULL ? strlen(filename) : c - filename); char *label; if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) { label = strdup(sym->name); } else if (bfd_is_const_section(sym->section)) { label = strprintf("%s<%.*s>", sym->name, flen, filename); } else { asymbol *gsym = canonical_symbol(sbfd, sym); if (gsym == NULL) label = strprintf("%s+%lx<%.*s>", sym->section->name, (unsigned long)sym->value, flen, filename); else if ((gsym->flags & BSF_GLOBAL) != 0) label = strdup(gsym->name); else if (static_local_symbol(sbfd, gsym)) label = strprintf("%s+%lx<%.*s>", static_local_symbol(sbfd, gsym), (unsigned long)sym->value, flen, filename); else label = strprintf("%s<%.*s>", gsym->name, flen, filename); } return label; } static void keep_span(struct span *span) { span->keep = true; span->ss->keep = true; } static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size) { struct span *span = vec_grow(&ss->spans, 1); span->size = size; span->contents_size = size; span->start = start; span->ss = ss; span->keep = true; span->new = false; span->patch = false; span->bugpatch = false; span->datapatch = false; span->precallable = strstarts(ss->name, ".ksplice_call_pre_apply") || strstarts(ss->name, ".ksplice_call_check_apply") || strstarts(ss->name, ".ksplice_call_fail_apply") || strstarts(ss->name, ".ksplice_call_post_remove"); span->match = NULL; vec_init(&span->entry_points); span->shift = 0; asymbol **symp = symbolp_scan(ss, span->start); if (symp != NULL) { span->symbol = *symp; span->label = label_lookup(ss->parent, span->symbol); } else { span->symbol = NULL; const char *label = label_lookup(ss->parent, ss->symbol); if (span->start != 0) span->label = strprintf("%s", label, (unsigned long)span->start); else span->label = label; } span->orig_label = span->label; return span; } static void initialize_string_spans(struct supersect *ss) { const char *str; for (str = ss->contents.data; (void *)str < ss->contents.data + ss->contents.size;) { bfd_vma start = (unsigned long)str - (unsigned long)ss->contents.data; bfd_vma size = strlen(str) + 1; bfd_vma contents_size = size; while ((start + size) % (1 << ss->alignment) != 0 && start + size < ss->contents.size) { /* Some string sections, like __ksymtab_strings, only align some strings with the declared alignment */ if (str[size] != '\0') break; size++; } struct span *span = new_span(ss, start, size); span->contents_size = contents_size; str += size; } } static int compare_ulongs(const void *va, const void *vb) { const unsigned long *a = va, *b = vb; return *a - *b; } static void initialize_table_spans(struct superbfd *sbfd, struct table_section *s) { asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect); if (isection == NULL) return; struct supersect *ss = fetch_supersect(sbfd, isection); if (ss->alignment < ffs(s->entry_align) - 1) ss->alignment = ffs(s->entry_align) - 1; asection *other_sect = NULL; if (s->other_sect != NULL) other_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect); struct supersect *other_ss = NULL; if (other_sect != NULL) other_ss = fetch_supersect(sbfd, other_sect); asection *crc_sect = NULL; if (s->crc_sect != NULL) crc_sect = bfd_get_section_by_name(sbfd->abfd, s->crc_sect); struct supersect *crc_ss = NULL; if (crc_sect != NULL) crc_ss = fetch_supersect(sbfd, crc_sect); struct ulong_vec offsets; vec_init(&offsets); void *entry; for (entry = ss->contents.data; entry < ss->contents.data + ss->contents.size; entry += s->entry_size) { struct span *span = new_span(ss, addr_offset(ss, entry), s->entry_size); if (s->entry_contents_size != 0) span->contents_size = s->entry_contents_size; if ((span->symbol == NULL || (span->symbol->flags & BSF_SECTION_SYM) != 0) && s->has_addr) { arelent *reloc = find_reloc(ss, entry + s->addr_offset); assert(reloc); struct span *target_span = reloc_target_span(ss, reloc); assert(target_span); asymbol *sym = *reloc->sym_ptr_ptr; unsigned long val = sym->value + reloc_target_offset(ss, reloc) - (target_span->start + target_span->shift); char *label = strprintf("%s", ss->name, target_span->label, val); change_initial_label(span, label); } if (other_sect != NULL) { asymbol *sym; bfd_vma offset = read_reloc(ss, entry + s->other_offset, sizeof(void *), &sym); if (sym->section == other_sect) { assert(offset >= 0 && offset < other_ss->contents.size); *vec_grow(&offsets, 1) = offset; } } if (crc_sect != NULL) new_span(crc_ss, addr_offset(ss, entry) / s->entry_size * s->crc_size, s->crc_size); if (ss->type == SS_TYPE_EXPORT) { const char *symname = read_string(ss, entry + s->other_offset); char *label = strprintf("%s:%s", ss->name, symname); change_initial_label(span, label); } } if (other_sect == NULL) return; *vec_grow(&offsets, 1) = 0; qsort(offsets.data, offsets.size, sizeof(*offsets.data), compare_ulongs); *vec_grow(&offsets, 1) = other_ss->contents.size; unsigned long *off; for (off = offsets.data; off < offsets.data + offsets.size - 1; off++) { if (*off != *(off + 1)) new_span(other_ss, *off, *(off + 1) - *off); } } static void initialize_table_section_spans(struct superbfd *sbfd) { struct supersect *tables_ss = fetch_supersect(offsets_sbfd, bfd_get_section_by_name(offsets_sbfd->abfd, ".ksplice_table_sections")); const struct table_section *ts; struct table_section s; for (ts = tables_ss->contents.data; (void *)ts < tables_ss->contents.data + tables_ss->contents.size; ts++) { s = *ts; s.sect = read_string(tables_ss, &ts->sect); s.other_sect = read_string(tables_ss, &ts->other_sect); s.crc_sect = read_string(tables_ss, &ts->crc_sect); initialize_table_spans(sbfd, &s); } } static void initialize_ksplice_call_spans(struct supersect *ss) { arelent **relocp; for (relocp = ss->relocs.data; relocp < ss->relocs.data + ss->relocs.size; relocp++) { arelent *reloc = *relocp; new_span(ss, reloc->address, bfd_get_reloc_size(reloc->howto)); /* the span labels should already be unique */ } } static void initialize_spans(struct superbfd *sbfd) { asection *sect; for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) { if (is_table_section(sect->name, true, true) && mode("keep")) continue; struct supersect *ss = fetch_supersect(sbfd, sect); if (ss->type == SS_TYPE_STRING) initialize_string_spans(ss); else if (ss->type == SS_TYPE_KSPLICE_CALL) initialize_ksplice_call_spans(ss); else new_span(ss, 0, ss->contents.size); } if (mode("keep")) initialize_table_section_spans(sbfd); } /* Returns the span pointed to by the relocation at span->start + offset */ static struct span *span_offset_target_span(struct span *span, int offset) { void *entry = span->ss->contents.data + span->start; arelent *reloc = find_reloc(span->ss, entry + offset); if (reloc == NULL) return NULL; return reloc_target_span(span->ss, reloc); } struct span *reloc_target_span(struct supersect *ss, arelent *reloc) { asymbol *sym_ptr = *reloc->sym_ptr_ptr; if (bfd_is_const_section(sym_ptr->section)) return NULL; bfd_vma addend = sym_ptr->value; if ((sym_ptr->flags & BSF_SECTION_SYM) != 0) addend += reloc_target_offset(ss, reloc); struct supersect *sym_ss = fetch_supersect(ss->parent, sym_ptr->section); struct span *span, *target_span = sym_ss->spans.data; for (span = sym_ss->spans.data; span < sym_ss->spans.data + sym_ss->spans.size; span++) { if (addend >= span->start && addend < span->start + span->size) target_span = span; } return target_span; } static bfd_vma reloc_target_offset(struct supersect *ss, arelent *reloc) { bfd_vma offset = reloc_offset(ss, reloc); if (reloc->howto->pc_relative) { if ((ss->flags & SEC_CODE) != 0) return offset + bfd_get_reloc_size(reloc->howto); const struct table_section *ts = get_table_section(ss->name); if (ts != NULL && ts->relative_addr && reloc->address % ts->entry_size == ts->addr_offset) return offset - ts->addr_offset; if (ts != NULL && ts->relative_other && reloc->address % ts->entry_size == ts->other_offset) return offset - ts->other_offset; DIE; } return offset; } struct span *find_span(struct supersect *ss, bfd_size_type address) { struct span *span; for (span = ss->spans.data; span < ss->spans.data + ss->spans.size; span++) { if (address >= span->start && address < span->start + span->size) return span; } /* Deal with empty BSS sections */ if (ss->contents.size == 0 && ss->spans.size > 0) return ss->spans.data; /* Deal with section end pointers */ if (address == ss->contents.size && ss->spans.size == 1) return ss->spans.data; return NULL; } void compute_span_shifts(struct superbfd *sbfd) { asection *sect; struct span *span; for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(sbfd, sect); if (!ss->keep) continue; bfd_size_type offset = 0; for (span = ss->spans.data; span < ss->spans.data + ss->spans.size; span++) { if (!span->keep) continue; span->shift = offset - span->start; offset += span->size; } } } void remove_unkept_spans(struct superbfd *sbfd) { asection *sect; struct span *span; for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(sbfd, sect); delete_obsolete_relocs(ss); struct arelentp_vec orig_relocs; vec_move(&orig_relocs, &ss->relocs); arelent **relocp, *reloc; for (relocp = orig_relocs.data; relocp < orig_relocs.data + orig_relocs.size; relocp++) { reloc = *relocp; asymbol *sym = *reloc->sym_ptr_ptr; span = reloc_target_span(ss, reloc); if ((span != NULL && span->keep && span->shift == 0) || bfd_is_const_section(sym->section)) { *vec_grow(&ss->relocs, 1) = reloc; continue; } struct supersect *sym_ss = fetch_supersect(sbfd, sym->section); if (span != NULL && (sym->flags & BSF_SECTION_SYM) == 0 && find_span(sym_ss, sym->value) != span) { err(sbfd, "Spans for symbol %s and relocation " "target do not match in sect %s\n", sym->name, sym_ss->name); DIE; } if (span != NULL && span->keep) { arelent *new_reloc = malloc(sizeof(*new_reloc)); *new_reloc = *reloc; new_reloc->addend = reloc_offset(ss, reloc); new_reloc->addend += span->shift; *vec_grow(&ss->new_relocs, 1) = new_reloc; } } } for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) { struct supersect *ss = fetch_supersect(sbfd, sect), orig_ss; if (!ss->keep) continue; supersect_move(&orig_ss, ss); vec_init(&ss->spans); for (span = orig_ss.spans.data; span < orig_ss.spans.data + orig_ss.spans.size; span++) { if (!span->keep) continue; struct span *new_span = vec_grow(&ss->spans, 1); *new_span = *span; new_span->start = span->start + span->shift; new_span->shift = 0; sect_copy(ss, sect_do_grow(ss, 1, span->size, 1), &orig_ss, orig_ss.contents.data + span->start, span->size); } } } static void init_objmanip_superbfd(struct superbfd *sbfd) { init_label_map(sbfd); initialize_supersect_types(sbfd); initialize_spans(sbfd); load_options(sbfd); compute_entry_points(sbfd); } void mangle_section_name(struct superbfd *sbfd, const char *name) { asection *sect = bfd_get_section_by_name(sbfd->abfd, name); if (sect == NULL) return; struct supersect *ss = fetch_supersect(sbfd, sect); ss->name = strprintf(".ksplice_pre.%s", ss->name); } static void write_bugline_patches(struct superbfd *sbfd) { const struct table_section *ts = get_table_section("__bug_table"); asection *sect = bfd_get_section_by_name(sbfd->abfd, "__bug_table"); if (sect == NULL) return; struct supersect *ss = fetch_supersect(sbfd, sect); assert(ts != NULL); void *entry; for (entry = ss->contents.data; entry < ss->contents.data + ss->contents.size; entry += ts->entry_size) { struct span *span = find_span(ss, addr_offset(ss, entry)); assert(span != NULL); if (!span->bugpatch) continue; arelent *reloc = find_reloc(ss, entry + ts->addr_offset); assert(reloc != NULL); asymbol *sym = *reloc->sym_ptr_ptr; assert(!bfd_is_const_section(sym->section)); struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches%s", sym->section->name); bfd_vma offset, start = 0; for (offset = 0; offset <= span->size; offset++) { if (offset != span->size && !part_of_reloc(ss, span->start + offset)) continue; if (start == offset) { start++; continue; } /* an interval of non-relocations just passed */ struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1, struct ksplice_patch); write_ksplice_patch_reloc (kpatch_ss, sym->section->name, &kpatch->oldaddr, sizeof(kpatch->oldaddr), span->label, start); char *data = write_patch_storage(kpatch_ss, kpatch, offset - start, NULL); memcpy(data, entry + start, offset - start); kpatch->type = KSPLICE_PATCH_DATA; start = offset + 1; } } } void *write_patch_storage(struct supersect *ss, struct ksplice_patch *kpatch, size_t size, struct supersect **data_ssp) { struct supersect *data_ss = make_section(ss->parent, ".ksplice_patch_data"); char *saved = sect_do_grow(data_ss, 1, size, 1); write_reloc(ss, &kpatch->saved, &data_ss->symbol, addr_offset(data_ss, saved)); char *data = sect_do_grow(data_ss, 1, size, 1); write_reloc(ss, &kpatch->contents, &data_ss->symbol, addr_offset(data_ss, data)); kpatch->size = size; if (data_ssp != NULL) *data_ssp = data_ss; return data; }