v2 splits the vendoring of libudis86 into importing the original files and
then patching them (and adding them to Makefile.am at that point).  It
also has both x86_64 and aarch64 implementations exit loops on rets or
unconditional jumps.

Jeremy Drake (5):
  Cygwin: factor out find_fast_cwd_pointer to arch-specific file.
  Cygwin: vendor libudis86 1.7.2/libudis86
  Cygwin: patch libudis86 to build as part of Cygwin
  Cygwin: use udis86 to find fast cwd pointer on x64
  Cygwin: add find_fast_cwd_pointer_aarch64.

 winsup/cygwin/Makefile.am              |   14 +-
 winsup/cygwin/fastcwd_aarch64.cc       |  203 +
 winsup/cygwin/path.cc                  |  145 +-
 winsup/cygwin/udis86/decode.c          | 1113 ++++
 winsup/cygwin/udis86/decode.h          |  195 +
 winsup/cygwin/udis86/extern.h          |  109 +
 winsup/cygwin/udis86/itab.c            | 8404 ++++++++++++++++++++++++
 winsup/cygwin/udis86/itab.h            |  680 ++
 winsup/cygwin/udis86/types.h           |  260 +
 winsup/cygwin/udis86/udint.h           |   91 +
 winsup/cygwin/udis86/udis86.c          |  464 ++
 winsup/cygwin/x86_64/fastcwd_x86_64.cc |  172 +
 12 files changed, 11727 insertions(+), 123 deletions(-)
 create mode 100644 winsup/cygwin/fastcwd_aarch64.cc
 create mode 100644 winsup/cygwin/udis86/decode.c
 create mode 100644 winsup/cygwin/udis86/decode.h
 create mode 100644 winsup/cygwin/udis86/extern.h
 create mode 100644 winsup/cygwin/udis86/itab.c
 create mode 100644 winsup/cygwin/udis86/itab.h
 create mode 100644 winsup/cygwin/udis86/types.h
 create mode 100644 winsup/cygwin/udis86/udint.h
 create mode 100644 winsup/cygwin/udis86/udis86.c
 create mode 100644 winsup/cygwin/x86_64/fastcwd_x86_64.cc

Range-diff against v1:
1:  fc59147412 = 1:  25a8b233f5 Cygwin: factor out find_fast_cwd_pointer to 
arch-specific file.
2:  5b5bccfc81 ! 2:  faa2688d1f Cygwin: vendor libudis86 1.7.2
    @@ Metadata
     Author: Jeremy Drake <cyg...@jdrake.com>

      ## Commit message ##
    -    Cygwin: vendor libudis86 1.7.2
    +    Cygwin: vendor libudis86 1.7.2/libudis86

         This does not include the source files responsible for generating AT&T-
    -    or Intel-syntax assembly output, and ifdefs out the large table of
    -    opcode strings since we're only interested in walking machine code, not
    -    generating disassembly.
    -
    -    Also included is a diff from the original libudis86 sources.
    +    or Intel-syntax assembly output, or upstream's Makefile.{am,in}.

         Signed-off-by: Jeremy Drake <cyg...@jdrake.com>

    - ## winsup/cygwin/Makefile.am ##
    -@@ winsup/cygwin/Makefile.am: LIB_NAME=libcygwin.a
    - # sources
    - #
    -
    --# These objects are included directly into the import library
    - if TARGET_X86_64
    - TARGET_FILES= \
    -   x86_64/bcopy.S \
    -@@ winsup/cygwin/Makefile.am: TARGET_FILES= \
    -   x86_64/wmempcpy.S
    - endif
    -
    -+# These objects are included directly into the import library
    - LIB_FILES= \
    -   lib/_cygwin_crt0_common.cc \
    -   lib/atexit.c \
    -@@ winsup/cygwin/Makefile.am: SEC_FILES= \
    - TZCODE_FILES= \
    -   tzcode/localtime_wrapper.c
    -
    -+if TARGET_X86_64
    -+UDIS86_FILES= \
    -+  udis86/decode.c \
    -+  udis86/itab.c \
    -+  udis86/udis86.c
    -+endif
    -+
    - DLL_FILES= \
    -   advapi32.cc \
    -   aio.cc \
    -@@ winsup/cygwin/Makefile.am: libdll_a_SOURCES= \
    -   $(MM_FILES) \
    -   $(SEC_FILES) \
    -   $(TZCODE_FILES) \
    -+  $(UDIS86_FILES) \
    -   $(GENERATED_FILES)
    -
    - #
    -@@ winsup/cygwin/Makefile.am: BUILT_SOURCES = \
    -
    - # Every time we touch a source file, the version info has to be rebuilt
    - # to maintain a correct build date, especially in uname release output
    --dirs = $(srcdir) $(srcdir)/fhandler $(srcdir)/lib $(srcdir)/libc 
$(srcdir)/math $(srcdir)/mm $(srcdir)/regex $(srcdir)/sec $(srcdir)/tzcode
    -+dirs = $(srcdir) $(srcdir)/fhandler $(srcdir)/lib $(srcdir)/libc 
$(srcdir)/math $(srcdir)/mm $(srcdir)/regex $(srcdir)/sec $(srcdir)/tzcode 
$(srcdir)/udis86
    - find_src_files = $(wildcard $(dir)/*.[chS]) $(wildcard $(dir)/*.cc)
    - src_files := $(foreach dir,$(dirs),$(find_src_files))
    -
    -
      ## winsup/cygwin/udis86/decode.c (new) ##
     @@
     +/* udis86 - libudis86/decode.c
    @@ winsup/cygwin/udis86/decode.c (new)
     + * (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 "winsup.h"
    -+#include "types.h"
     +#include "udint.h"
    ++#include "types.h"
     +#include "decode.h"
     +
     +#ifndef __UD_STANDALONE__
    @@ winsup/cygwin/udis86/decode.c (new)
     +decode_prefixes(struct ud *u)
     +{
     +  int done = 0;
    -+  uint8_t curr = 0, last = 0;
    ++  uint8_t curr, last = 0;
     +  UD_RETURN_ON_ERROR(u);
     +
     +  do {
    @@ winsup/cygwin/udis86/decode.c (new)
     +      break;
     +    case OP_F:
     +      u->br_far  = 1;
    -+      fallthrough;
    ++      /* intended fall through */
     +    case OP_M:
     +      if (MODRM_MOD(modrm(u)) == 3) {
     +        UDERR(u, "expected modrm.mod != 3\n");
     +      }
    -+      fallthrough;
    ++      /* intended fall through */
     +    case OP_E:
     +      decode_modrm_rm(u, operand, REGCLASS_GPR, size);
     +      break;
    @@ winsup/cygwin/udis86/decode.c (new)
     +      if (MODRM_MOD(modrm(u)) != 3) {
     +        UDERR(u, "expected modrm.mod == 3\n");
     +      }
    -+      fallthrough;
    ++      /* intended fall through */
     +    case OP_Q:
     +      decode_modrm_rm(u, operand, REGCLASS_MMX, size);
     +      break;
    @@ winsup/cygwin/udis86/decode.c (new)
     +      if (MODRM_MOD(modrm(u)) != 3) {
     +        UDERR(u, "expected modrm.mod == 3\n");
     +      }
    -+      fallthrough;
    ++      /* intended fall through */
     +    case OP_W:
     +      decode_modrm_rm(u, operand, REGCLASS_XMM, size);
     +      break;
    @@ winsup/cygwin/udis86/decode.h (new)
     +  return (primary_opcode & 0x02) != 0;
     +}
     +
    -+extern const struct ud_itab_entry ud_itab[];
    -+extern const struct ud_lookup_table_list_entry ud_lookup_table_list[];
    ++extern struct ud_itab_entry ud_itab[];
    ++extern struct ud_lookup_table_list_entry ud_lookup_table_list[];
     +
     +#endif /* UD_DECODE_H */
     +
    @@ winsup/cygwin/udis86/extern.h (new)
     +
     +extern unsigned int ud_disassemble(struct ud*);
     +
    -+#ifndef __INSIDE_CYGWIN__
     +extern void ud_translate_intel(struct ud*);
     +
     +extern void ud_translate_att(struct ud*);
    -+#endif /* __INSIDE_CYGWIN__ */
     +
     +extern const char* ud_insn_asm(const struct ud* u);
     +
    @@ winsup/cygwin/udis86/extern.h (new)
     +
     +extern enum ud_mnemonic_code ud_insn_mnemonic(const struct ud *u);
     +
    -+#ifndef __INSIDE_CYGWIN__
     +extern const char* ud_lookup_mnemonic(enum ud_mnemonic_code c);
    -+#endif /* __INSIDE_CYGWIN__ */
     +
     +extern void ud_set_user_opaque_data(struct ud*, void*);
     +
    @@ winsup/cygwin/udis86/extern.h (new)
      ## winsup/cygwin/udis86/itab.c (new) ##
     @@
     +/* itab.c -- generated by udis86:scripts/ud_itab.py, do no edit */
    -+#include "winsup.h"
     +#include "decode.h"
     +
     +#define GROUP(n) (0x8000 | (n))
    @@ winsup/cygwin/udis86/itab.c (new)
     +};
     +
     +
    -+const struct ud_lookup_table_list_entry ud_lookup_table_list[] = {
    ++struct ud_lookup_table_list_entry ud_lookup_table_list[] = {
     +    /* 000 */ { ud_itab__0, UD_TAB__OPC_TABLE, "table0" },
     +    /* 001 */ { ud_itab__1, UD_TAB__OPC_MODE, "/m" },
     +    /* 002 */ { ud_itab__2, UD_TAB__OPC_MODE, "/m" },
    @@ winsup/cygwin/udis86/itab.c (new)
     +#define O_sIv     { OP_sI,       SZ_V     }
     +#define O_sIz     { OP_sI,       SZ_Z     }
     +
    -+const struct ud_itab_entry ud_itab[] = {
    ++struct ud_itab_entry ud_itab[] = {
     +  /* 0000 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none },
     +  /* 0001 */ { UD_Iadd, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb },
     +  /* 0002 */ { UD_Iadd, O_Ev, O_Gv, O_NONE, 
P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb },
    @@ winsup/cygwin/udis86/itab.c (new)
     +};
     +
     +
    -+#ifndef __INSIDE_CYGWIN__
     +const char * ud_mnemonics_str[] = {
     +"invalid",
     +    "3dnow",
    @@ winsup/cygwin/udis86/itab.c (new)
     +    "movbe",
     +    "crc32"
     +};
    -+#endif /* __INSIDE_CYGWIN__ */

      ## winsup/cygwin/udis86/itab.h (new) ##
     @@
    @@ winsup/cygwin/udis86/itab.h (new)
     +    UD_MAX_MNEMONIC_CODE
     +} UD_ATTR_PACKED;
     +
    -+#ifndef __INSIDE_CYGWIN__
     +extern const char * ud_mnemonics_str[];
    -+#endif /* __INSIDE_CYGWIN__ */
     +
     +#endif /* UD_ITAB_H */

    @@ winsup/cygwin/udis86/types.h (new)
     +#endif
     +#endif /* __KERNEL__ */
     +
    -+#ifdef __INSIDE_CYGWIN__
    -+# include <inttypes.h>
    -+# ifndef __UD_STANDALONE__
    -+#  define __UD_STANDALONE__ 1
    -+# endif
    -+#endif /* __INSIDE_CYGWIN__ */
    -+
    -+
     +#if defined(_MSC_VER) || defined(__BORLANDC__)
     +# include <stdint.h>
     +# include <stdio.h>
    @@ winsup/cygwin/udis86/types.h (new)
     +  uint8_t   modrm;
     +  uint8_t   primary_opcode;
     +  void *    user_opaque_data;
    -+  const struct ud_itab_entry * itab_entry;
    -+  const struct ud_lookup_table_list_entry *le;
    ++  struct ud_itab_entry * itab_entry;
    ++  struct ud_lookup_table_list_entry *le;
     +};
     +
     +/* 
-----------------------------------------------------------------------------
    @@ winsup/cygwin/udis86/types.h (new)
     +typedef struct ud             ud_t;
     +typedef struct ud_operand     ud_operand_t;
     +
    -+#ifndef __INSIDE_CYGWIN__
     +#define UD_SYN_INTEL          ud_translate_intel
     +#define UD_SYN_ATT            ud_translate_att
    -+#endif /* __INSIDE_CYGWIN__ */
     +#define UD_EOI                (-1)
     +#define UD_INP_CACHE_SZ       32
     +#define UD_VENDOR_AMD         0
    @@ winsup/cygwin/udis86/udint.h (new)
     +#ifndef _UDINT_H_
     +#define _UDINT_H_
     +
    -+#ifndef __INSIDE_CYGWIN__
    -+# ifdef HAVE_CONFIG_H
    -+#  include <config.h>
    -+# endif /* HAVE_CONFIG_H */
    -+#endif /* __INSIDE_CYGWIN__ */
    ++#ifdef HAVE_CONFIG_H
    ++# include <config.h>
    ++#endif /* HAVE_CONFIG_H */
     +
     +#if defined(UD_DEBUG) && HAVE_ASSERT_H
     +# include <assert.h>
    @@ winsup/cygwin/udis86/udint.h (new)
     +
     +#endif /* _UDINT_H_ */

    - ## winsup/cygwin/udis86/udis86-modifications.diff (new) ##
    -@@
    -+diff -ur udis86-1.7.2/libudis86/decode.c udis86/decode.c
    -+--- udis86-1.7.2/libudis86/decode.c
    -++++ udis86/decode.c
    -+@@ -23,8 +23,9 @@
    -+  * (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 "udint.h"
    -++#include "winsup.h"
    -+ #include "types.h"
    -++#include "udint.h"
    -+ #include "decode.h"
    -+
    -+ #ifndef __UD_STANDALONE__
    -+@@ -204,7 +205,7 @@
    -+ decode_prefixes(struct ud *u)
    -+ {
    -+   int done = 0;
    -+-  uint8_t curr, last = 0;
    -++  uint8_t curr = 0, last = 0;
    -+   UD_RETURN_ON_ERROR(u);
    -+
    -+   do {
    -+@@ -653,12 +654,12 @@
    -+       break;
    -+     case OP_F:
    -+       u->br_far  = 1;
    -+-      /* intended fall through */
    -++      fallthrough;
    -+     case OP_M:
    -+       if (MODRM_MOD(modrm(u)) == 3) {
    -+         UDERR(u, "expected modrm.mod != 3\n");
    -+       }
    -+-      /* intended fall through */
    -++      fallthrough;
    -+     case OP_E:
    -+       decode_modrm_rm(u, operand, REGCLASS_GPR, size);
    -+       break;
    -+@@ -677,7 +678,7 @@
    -+       if (MODRM_MOD(modrm(u)) != 3) {
    -+         UDERR(u, "expected modrm.mod == 3\n");
    -+       }
    -+-      /* intended fall through */
    -++      fallthrough;
    -+     case OP_Q:
    -+       decode_modrm_rm(u, operand, REGCLASS_MMX, size);
    -+       break;
    -+@@ -688,7 +689,7 @@
    -+       if (MODRM_MOD(modrm(u)) != 3) {
    -+         UDERR(u, "expected modrm.mod == 3\n");
    -+       }
    -+-      /* intended fall through */
    -++      fallthrough;
    -+     case OP_W:
    -+       decode_modrm_rm(u, operand, REGCLASS_XMM, size);
    -+       break;
    -+diff -ur udis86-1.7.2/libudis86/decode.h udis86/decode.h
    -+--- udis86-1.7.2/libudis86/decode.h
    -++++ udis86/decode.h
    -+@@ -183,8 +183,8 @@
    -+   return (primary_opcode & 0x02) != 0;
    -+ }
    -+
    -+-extern struct ud_itab_entry ud_itab[];
    -+-extern struct ud_lookup_table_list_entry ud_lookup_table_list[];
    -++extern const struct ud_itab_entry ud_itab[];
    -++extern const struct ud_lookup_table_list_entry ud_lookup_table_list[];
    -+
    -+ #endif /* UD_DECODE_H */
    -+
    -+diff -ur udis86-1.7.2/libudis86/extern.h udis86/extern.h
    -+--- udis86-1.7.2/libudis86/extern.h
    -++++ udis86/extern.h
    -+@@ -60,9 +60,11 @@
    -+
    -+ extern unsigned int ud_disassemble(struct ud*);
    -+
    -++#ifndef __INSIDE_CYGWIN__
    -+ extern void ud_translate_intel(struct ud*);
    -+
    -+ extern void ud_translate_att(struct ud*);
    -++#endif /* __INSIDE_CYGWIN__ */
    -+
    -+ extern const char* ud_insn_asm(const struct ud* u);
    -+
    -+@@ -82,7 +84,9 @@
    -+
    -+ extern enum ud_mnemonic_code ud_insn_mnemonic(const struct ud *u);
    -+
    -++#ifndef __INSIDE_CYGWIN__
    -+ extern const char* ud_lookup_mnemonic(enum ud_mnemonic_code c);
    -++#endif /* __INSIDE_CYGWIN__ */
    -+
    -+ extern void ud_set_user_opaque_data(struct ud*, void*);
    -+
    -+diff -ur udis86-1.7.2/libudis86/itab.c udis86/itab.c
    -+--- udis86-1.7.2/libudis86/itab.c
    -++++ udis86/itab.c
    -+@@ -1,4 +1,5 @@
    -+ /* itab.c -- generated by udis86:scripts/ud_itab.py, do no edit */
    -++#include "winsup.h"
    -+ #include "decode.h"
    -+
    -+ #define GROUP(n) (0x8000 | (n))
    -+@@ -5028,7 +5029,7 @@
    -+ };
    -+
    -+
    -+-struct ud_lookup_table_list_entry ud_lookup_table_list[] = {
    -++const struct ud_lookup_table_list_entry ud_lookup_table_list[] = {
    -+     /* 000 */ { ud_itab__0, UD_TAB__OPC_TABLE, "table0" },
    -+     /* 001 */ { ud_itab__1, UD_TAB__OPC_MODE, "/m" },
    -+     /* 002 */ { ud_itab__2, UD_TAB__OPC_MODE, "/m" },
    -+@@ -6294,7 +6295,7 @@
    -+ #define O_sIv     { OP_sI,       SZ_V     }
    -+ #define O_sIz     { OP_sI,       SZ_Z     }
    -+
    -+-struct ud_itab_entry ud_itab[] = {
    -++const struct ud_itab_entry ud_itab[] = {
    -+   /* 0000 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none },
    -+   /* 0001 */ { UD_Iadd, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb },
    -+   /* 0002 */ { UD_Iadd, O_Ev, O_Gv, O_NONE, 
P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb },
    -+@@ -7749,6 +7750,7 @@
    -+ };
    -+
    -+
    -++#ifndef __INSIDE_CYGWIN__
    -+ const char * ud_mnemonics_str[] = {
    -+ "invalid",
    -+     "3dnow",
    -+@@ -8399,3 +8401,4 @@
    -+     "movbe",
    -+     "crc32"
    -+ };
    -++#endif /* __INSIDE_CYGWIN__ */
    -+diff -ur udis86-1.7.2/libudis86/itab.h udis86/itab.h
    -+--- udis86-1.7.2/libudis86/itab.h
    -++++ udis86/itab.h
    -+@@ -673,6 +673,8 @@
    -+     UD_MAX_MNEMONIC_CODE
    -+ } UD_ATTR_PACKED;
    -+
    -++#ifndef __INSIDE_CYGWIN__
    -+ extern const char * ud_mnemonics_str[];
    -++#endif /* __INSIDE_CYGWIN__ */
    -+
    -+ #endif /* UD_ITAB_H */
    -+Only in udis86-1.7.2/libudis86/: Makefile.am
    -+Only in udis86-1.7.2/libudis86/: Makefile.in
    -+Only in udis86-1.7.2/libudis86/: syn.c
    -+Only in udis86-1.7.2/libudis86/: syn.h
    -+Only in udis86-1.7.2/libudis86/: syn-att.c
    -+Only in udis86-1.7.2/libudis86/: syn-intel.c
    -+diff -ur udis86-1.7.2/libudis86/types.h udis86/types.h
    -+--- udis86-1.7.2/libudis86/types.h
    -++++ udis86/types.h
    -+@@ -36,6 +36,14 @@
    -+ #endif
    -+ #endif /* __KERNEL__ */
    -+
    -++#ifdef __INSIDE_CYGWIN__
    -++# include <inttypes.h>
    -++# ifndef __UD_STANDALONE__
    -++#  define __UD_STANDALONE__ 1
    -++# endif
    -++#endif /* __INSIDE_CYGWIN__ */
    -++
    -++
    -+ #if defined(_MSC_VER) || defined(__BORLANDC__)
    -+ # include <stdint.h>
    -+ # include <stdio.h>
    -+@@ -221,8 +229,8 @@
    -+   uint8_t   modrm;
    -+   uint8_t   primary_opcode;
    -+   void *    user_opaque_data;
    -+-  struct ud_itab_entry * itab_entry;
    -+-  struct ud_lookup_table_list_entry *le;
    -++  const struct ud_itab_entry * itab_entry;
    -++  const struct ud_lookup_table_list_entry *le;
    -+ };
    -+
    -+ /* 
-----------------------------------------------------------------------------
    -+@@ -235,8 +243,10 @@
    -+ typedef struct ud             ud_t;
    -+ typedef struct ud_operand     ud_operand_t;
    -+
    -++#ifndef __INSIDE_CYGWIN__
    -+ #define UD_SYN_INTEL          ud_translate_intel
    -+ #define UD_SYN_ATT            ud_translate_att
    -++#endif /* __INSIDE_CYGWIN__ */
    -+ #define UD_EOI                (-1)
    -+ #define UD_INP_CACHE_SZ       32
    -+ #define UD_VENDOR_AMD         0
    -+diff -ur udis86-1.7.2/libudis86/udint.h udis86/udint.h
    -+--- udis86-1.7.2/libudis86/udint.h
    -++++ udis86/udint.h
    -+@@ -26,9 +26,11 @@
    -+ #ifndef _UDINT_H_
    -+ #define _UDINT_H_
    -+
    -+-#ifdef HAVE_CONFIG_H
    -+-# include <config.h>
    -+-#endif /* HAVE_CONFIG_H */
    -++#ifndef __INSIDE_CYGWIN__
    -++# ifdef HAVE_CONFIG_H
    -++#  include <config.h>
    -++# endif /* HAVE_CONFIG_H */
    -++#endif /* __INSIDE_CYGWIN__ */
    -+
    -+ #if defined(UD_DEBUG) && HAVE_ASSERT_H
    -+ # include <assert.h>
    -+diff -ur udis86-1.7.2/libudis86/udis86.c udis86/udis86.c
    -+--- udis86-1.7.2/libudis86/udis86.c
    -++++ udis86/udis86.c
    -+@@ -24,8 +24,9 @@
    -+  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    -+  */
    -+
    -+-#include "udint.h"
    -++#include "winsup.h"
    -+ #include "extern.h"
    -++#include "udint.h"
    -+ #include "decode.h"
    -+
    -+ #if !defined(__UD_STANDALONE__)
    -+@@ -34,6 +35,10 @@
    -+ # endif
    -+ #endif /* !__UD_STANDALONE__ */
    -+
    -++#ifdef __INSIDE_CYGWIN__
    -++#define sprintf __small_sprintf
    -++#endif /* __INSIDE_CYGWIN__ */
    -++
    -+ static void ud_inp_init(struct ud *u);
    -+
    -+ /* 
=============================================================================
    -+@@ -324,6 +329,7 @@
    -+ }
    -+
    -+
    -++#ifndef __INSIDE_CYGWIN__
    -+ /* 
=============================================================================
    -+  * ud_lookup_mnemonic
    -+  *    Looks up mnemonic code in the mnemonic string table.
    -+@@ -339,6 +345,7 @@
    -+     return NULL;
    -+   }
    -+ }
    -++#endif /* __INSIDE_CYGWIN__ */
    -+
    -+
    -+ /*
    -
      ## winsup/cygwin/udis86/udis86.c (new) ##
     @@
     +/* udis86 - libudis86/udis86.c
    @@ winsup/cygwin/udis86/udis86.c (new)
     + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     + */
     +
    -+#include "winsup.h"
    -+#include "extern.h"
     +#include "udint.h"
    ++#include "extern.h"
     +#include "decode.h"
     +
     +#if !defined(__UD_STANDALONE__)
    @@ winsup/cygwin/udis86/udis86.c (new)
     +# endif
     +#endif /* !__UD_STANDALONE__ */
     +
    -+#ifdef __INSIDE_CYGWIN__
    -+#define sprintf __small_sprintf
    -+#endif /* __INSIDE_CYGWIN__ */
    -+
     +static void ud_inp_init(struct ud *u);
     +
     +/* 
=============================================================================
    @@ winsup/cygwin/udis86/udis86.c (new)
     +}
     +
     +
    -+#ifndef __INSIDE_CYGWIN__
     +/* 
=============================================================================
     + * ud_lookup_mnemonic
     + *    Looks up mnemonic code in the mnemonic string table.
    @@ winsup/cygwin/udis86/udis86.c (new)
     +    return NULL;
     +  }
     +}
    -+#endif /* __INSIDE_CYGWIN__ */
     +
     +
     +/*
-:  ---------- > 3:  04f7a44f59 Cygwin: patch libudis86 to build as part of 
Cygwin
3:  1c712acab4 ! 4:  0f06e96562 Cygwin: use udis86 to find fast cwd pointer on 
x64
    @@ winsup/cygwin/x86_64/fastcwd_x86_64.cc

     -#define peek32(x) (*(int32_t *)(x))
     +static inline const void *
    -+rip_rel_offset (const ud_t *ud_obj, const ud_operand_t *opr, int 
additional=0)
    ++rip_rel_offset (const ud_t *ud_obj, const ud_operand_t *opr, int 
sub_off=0)
     +{
     +  return (const void *) (ud_insn_off (ud_obj) + ud_insn_len (ud_obj) +
    -+                   opr->lval.sdword + additional);
    ++                   opr->lval.sdword - sub_off);
     +}

      /* This function scans the code in ntdll.dll to find the address of the
    @@ winsup/cygwin/x86_64/fastcwd_x86_64.cc: find_fast_cwd_pointer_x86_64 ()
     +  ud_set_input_buffer (&ud_obj, get_dir, 80);
     +  ud_set_pc (&ud_obj, (const uint64_t) get_dir);
     +  const ud_operand_t *opr;
    ++  ud_mnemonic_code_t insn;
        /* Search first relative call instruction in RtlGetCurrentDirectory_U. 
*/
     -  const uint8_t *rcall = (const uint8_t *) memchr (get_dir, 0xe8, 80);
     -  if (!rcall)
     +  const uint8_t *use_cwd = NULL;
    -+  while (ud_disassemble (&ud_obj))
    ++  while (ud_disassemble (&ud_obj) &&
    ++      (insn = ud_insn_mnemonic (&ud_obj)) != UD_Iret &&
    ++      insn != UD_Ijmp)
     +    {
    -+      if (ud_insn_mnemonic (&ud_obj) == UD_Icall)
    ++      if (insn == UD_Icall)
     +  {
     +    opr = ud_insn_opr (&ud_obj, 0);
     +    if (opr->type == UD_OP_JIMM && opr->size == 32)
    @@ winsup/cygwin/x86_64/fastcwd_x86_64.cc: find_fast_cwd_pointer_x86_64 ()
     +  PRTL_CRITICAL_SECTION lockaddr = NULL;
     +
     +  /* both cases have an `lea rel(%rip)` on the lock */
    -+  while (ud_disassemble (&ud_obj))
    ++  while (ud_disassemble (&ud_obj) &&
    ++      (insn = ud_insn_mnemonic (&ud_obj)) != UD_Iret &&
    ++      insn != UD_Ijmp)
          {
     -      /* The lock instruction tweaks the LockCount member, which is not at
     -   the start of the PRTL_CRITICAL_SECTION structure.  So we have to
    @@ winsup/cygwin/x86_64/fastcwd_x86_64.cc: find_fast_cwd_pointer_x86_64 ()
     -   near to the locking stuff. */
     -      movrbx = (const uint8_t *) memmem ((const char *) lock, 40,
     -                                         "\x48\x8b\x1d", 3);
    -+      if (ud_insn_mnemonic (&ud_obj) == UD_Ilea)
    ++      if (insn == UD_Ilea)
     +  {
     +    /* this seems to follow intel syntax, in that operand 0 is the
     +       dest and 1 is the src */
    @@ winsup/cygwin/x86_64/fastcwd_x86_64.cc: find_fast_cwd_pointer_x86_64 ()
     +
     +  /* Next is either the `callq RtlEnterCriticalSection', or on Windows 8,
     +     a `lock btr` */
    -+  while (ud_disassemble (&ud_obj))
    ++  bool found = false;
    ++  while (ud_disassemble (&ud_obj) &&
    ++      (insn = ud_insn_mnemonic (&ud_obj)) != UD_Iret &&
    ++      insn != UD_Ijmp)
          {
     -      /* Usually the callq RtlEnterCriticalSection follows right after
     -   fetching the lock address. */
    @@ winsup/cygwin/x86_64/fastcwd_x86_64.cc: find_fast_cwd_pointer_x86_64 ()
     -      lock = (const uint8_t *) memmem ((const char *) use_cwd, 80,
     -                                       "\x48\x8d\x0d", 3);
     -      if (!lock)
    -+      ud_mnemonic_code_t insn = ud_insn_mnemonic (&ud_obj);
     +      if (insn == UD_Icall)
        {
     -    /* Windows 8.1 Preview calls `lea rel(rip),%r12' then some unrelated
    @@ winsup/cygwin/x86_64/fastcwd_x86_64.cc: find_fast_cwd_pointer_x86_64 ()
     +      {
     +        if (ent_crit != rip_rel_offset (&ud_obj, opr))
     +          return NULL;
    ++        found = true;
     +        break;
     +      }
        }
    @@ winsup/cygwin/x86_64/fastcwd_x86_64.cc: find_fast_cwd_pointer_x86_64 ()
     +        opr->size == 32)
     +      {
     +        if (lockaddr != rip_rel_offset (&ud_obj, opr,
    -+                      -(int) offsetof (RTL_CRITICAL_SECTION, LockCount)))
    ++                            offsetof (RTL_CRITICAL_SECTION, LockCount)))
     +          return NULL;
    -+
    ++        found = true;
     +        break;
     +      }
        }
     +    }
    ++  if (!found)
    ++    return NULL;

     -      if (!lock)
     +  fcwd_access_t **f_cwd_ptr = NULL;
     +  ud_type_t reg = UD_NONE;
     +  /* now we're looking for a movq rel(%rip) */
    -+  while (ud_disassemble (&ud_obj))
    ++  while (ud_disassemble (&ud_obj) &&
    ++      (insn = ud_insn_mnemonic (&ud_obj)) != UD_Iret &&
    ++      insn != UD_Ijmp)
     +    {
    -+      if (ud_insn_mnemonic (&ud_obj) == UD_Imov)
    ++      if (insn == UD_Imov)
        {
     -    return NULL;
     +    const ud_operand_t *opr0 = ud_insn_opr (&ud_obj, 0);
    @@ winsup/cygwin/x86_64/fastcwd_x86_64.cc: find_fast_cwd_pointer_x86_64 ()
     -  const uint8_t *testrbx = (const uint8_t *)
     -                     memmem (movrbx + 7, 3, "\x48\x85\xdb", 3);
     -  if (!testrbx)
    -+  if (!ud_disassemble (&ud_obj) || ud_insn_mnemonic (&ud_obj) != UD_Itest)
    ++  if (!f_cwd_ptr || !ud_disassemble (&ud_obj) ||
    ++      ud_insn_mnemonic (&ud_obj) != UD_Itest)
     +    return NULL;
     +
     +  opr = ud_insn_opr (&ud_obj, 0);
4:  56d9b81dea ! 5:  e3adc20c9f Cygwin: add find_fast_cwd_pointer_aarch64.
    @@ winsup/cygwin/fastcwd_aarch64.cc (new)
     +#endif
     +}
     +
    ++/* these ids and masks, as well as the names of the various other parts of
    ++   instructions used in this file, came from
    ++   
https://developer.arm.com/documentation/ddi0602/2024-09/Index-by-Encoding
    ++   (Arm A-profile A64 Instruction Set Architecture)
    ++*/
     +#define IS_INSN(pc, name) ((*(pc) & name##_mask) == name##_id)
     +static const uint32_t add_id = 0x11000000;
     +static const uint32_t add_mask = 0x7fc00000;
     +static const uint32_t adrp_id = 0x90000000;
     +static const uint32_t adrp_mask = 0x9f000000;
    ++static const uint32_t b_id = 0x14000000;
    ++static const uint32_t b_mask = 0xfc000000;
     +static const uint32_t bl_id = 0x94000000;
     +static const uint32_t bl_mask = 0xfc000000;
     +/* matches both cbz and cbnz */
    @@ winsup/cygwin/fastcwd_aarch64.cc (new)
     +static const uint32_t cbz_mask = 0x7e000000;
     +static const uint32_t ldr_id = 0xb9400000;
     +static const uint32_t ldr_mask = 0xbfc00000;
    ++/* matches both ret and br (which are the same except ret is a 'hint' that
    ++   it's  a subroutine return */
    ++static const uint32_t ret_id = 0xd61f0000;
    ++static const uint32_t ret_mask = 0xffbffc1f;
     +
    ++/* this would work for either bl or b, but we only use it for bl */
     +static inline LPCVOID
     +extract_bl_target (const uint32_t * pc)
     +{
    -+  assert (IS_INSN (pc, bl));
    ++  assert (IS_INSN (pc, bl) || IS_INSN (pc, b));
     +  int32_t offset = *pc & ~bl_mask;
     +  /* sign extend */
     +  if (offset & (1 << 25))
    @@ winsup/cygwin/fastcwd_aarch64.cc (new)
     +fcwd_access_t **
     +find_fast_cwd_pointer_aarch64 ()
     +{
    -+  LPCVOID proc = GetArm64ProcAddress (GetModuleHandle ("ntdll"),
    -+                                "RtlGetCurrentDirectory_U");
    -+  const uint32_t *start = (uint32_t *) proc;
    ++  /* Fetch entry points of relevant functions in ntdll.dll. */
    ++  HMODULE ntdll = GetModuleHandle ("ntdll.dll");
    ++  if (!ntdll)
    ++    return NULL;
    ++  LPCVOID get_dir = GetArm64ProcAddress (ntdll, 
"RtlGetCurrentDirectory_U");
    ++  LPCVOID ent_crit = GetArm64ProcAddress (ntdll, 
"RtlEnterCriticalSection");
    ++  if (!get_dir || !ent_crit)
    ++    return NULL;
    ++
    ++  LPCVOID use_cwd = NULL;
    ++  const uint32_t *start = (const uint32_t *) get_dir;
     +  const uint32_t *pc = start;
     +  /* find the call to RtlpReferenceCurrentDirectory, and get its address 
*/
    -+  for (; pc < start + 20; pc++)
    ++  for (; pc < start + 20 && !IS_INSN (pc, ret) && !IS_INSN (pc, b); pc++)
     +    {
     +      if (IS_INSN (pc, bl))
     +  {
    -+    proc = extract_bl_target (pc);
    ++    use_cwd = extract_bl_target (pc);
     +    break;
     +  }
     +    }
    -+  if (proc == start)
    ++  if (!use_cwd)
     +    return NULL;
     +
    -+  start = pc = (uint32_t *) proc;
    ++  start = pc = (const uint32_t *) use_cwd;
     +
     +  const uint32_t *ldrpc = NULL;
     +  uint32_t ldroffset, ldrsz;
     +  uint32_t ldrrn, ldrrd;
     +
     +  /* find the ldr (immediate unsigned offset) for RtlpCurDirRef */
    -+  for (; pc < start + 20; pc++)
    ++  for (; pc < start + 20 && !IS_INSN (pc, ret) && !IS_INSN (pc, b); pc++)
     +    {
     +      if (IS_INSN (pc, ldr))
     +  {
    @@ winsup/cygwin/fastcwd_aarch64.cc (new)
     +  /* work backwards, find a bl to RtlEnterCriticalSection whose argument
     +     is the fast peb lock */
     +
    -+  proc = GetArm64ProcAddress (GetModuleHandle ("ntdll"),
    -+                        "RtlEnterCriticalSection");
     +  for (pc = ldrpc; pc >= start; pc--)
     +    {
    -+      if (IS_INSN (pc, bl) && extract_bl_target (pc) == proc)
    ++      if (IS_INSN (pc, bl) && extract_bl_target (pc) == ent_crit)
     +  break;
     +    }
     +  uint32_t addoffset;
-- 
2.48.1.windows.1

Reply via email to