diff --git a/src/syscall/syscall_bsd.go b/src/syscall/syscall_bsd.go
index b52de7450ff1df3a1e091328d19a79ddd81f8025..1c7ec588bcf3f728bece9d68c110aac5d9bbd722 100644
--- a/src/syscall/syscall_bsd.go
+++ b/src/syscall/syscall_bsd.go
@@ -17,6 +17,21 @@ import (
 	"unsafe"
 )
 
+const ImplementsGetwd = true
+
+func Getwd() (string, error) {
+	var buf [pathMax]byte
+	_, err := getcwd(buf[:])
+	if err != nil {
+		return "", err
+	}
+	n := clen(buf[:])
+	if n < 1 {
+		return "", EINVAL
+	}
+	return string(buf[:n]), nil
+}
+
 /*
  * Wrapped
  */
diff --git a/src/syscall/syscall_darwin.go b/src/syscall/syscall_darwin.go
index c84547c628c0342213bfb4ab4e26ad74f134e4ae..afdadbf89468d728cc94613ab3c7f0d6c6afb529 100644
--- a/src/syscall/syscall_darwin.go
+++ b/src/syscall/syscall_darwin.go
@@ -12,28 +12,7 @@
 
 package syscall
 
-import (
-	errorspkg "errors"
-	"unsafe"
-)
-
-const ImplementsGetwd = true
-
-func Getwd() (string, error) {
-	buf := make([]byte, 2048)
-	attrs, err := getAttrList(".", attrList{CommonAttr: attrCmnFullpath}, buf, 0)
-	if err == nil && len(attrs) == 1 && len(attrs[0]) >= 2 {
-		wd := string(attrs[0])
-		// Sanity check that it's an absolute path and ends
-		// in a null byte, which we then strip.
-		if wd[0] == '/' && wd[len(wd)-1] == 0 {
-			return wd[:len(wd)-1], nil
-		}
-	}
-	// If pkg/os/getwd.go gets ENOTSUP, it will fall back to the
-	// slow algorithm.
-	return "", ENOTSUP
-}
+import "unsafe"
 
 type SockaddrDatalink struct {
 	Len    uint8
@@ -94,7 +73,6 @@ const (
 	attrBitMapCount = 5
 	attrCmnModtime  = 0x00000400
 	attrCmnAcctime  = 0x00001000
-	attrCmnFullpath = 0x08000000
 )
 
 type attrList struct {
@@ -107,66 +85,6 @@ type attrList struct {
 	Forkattr    uint32
 }
 
-func getAttrList(path string, attrList attrList, attrBuf []byte, options uint) (attrs [][]byte, err error) {
-	if len(attrBuf) < 4 {
-		return nil, errorspkg.New("attrBuf too small")
-	}
-	attrList.bitmapCount = attrBitMapCount
-
-	var _p0 *byte
-	_p0, err = BytePtrFromString(path)
-	if err != nil {
-		return nil, err
-	}
-
-	_, _, e1 := syscall6(
-		funcPC(libc_getattrlist_trampoline),
-		uintptr(unsafe.Pointer(_p0)),
-		uintptr(unsafe.Pointer(&attrList)),
-		uintptr(unsafe.Pointer(&attrBuf[0])),
-		uintptr(len(attrBuf)),
-		uintptr(options),
-		0,
-	)
-	if e1 != 0 {
-		return nil, e1
-	}
-	size := *(*uint32)(unsafe.Pointer(&attrBuf[0]))
-
-	// dat is the section of attrBuf that contains valid data,
-	// without the 4 byte length header. All attribute offsets
-	// are relative to dat.
-	dat := attrBuf
-	if int(size) < len(attrBuf) {
-		dat = dat[:size]
-	}
-	dat = dat[4:] // remove length prefix
-
-	for i := uint32(0); int(i) < len(dat); {
-		header := dat[i:]
-		if len(header) < 8 {
-			return attrs, errorspkg.New("truncated attribute header")
-		}
-		datOff := *(*int32)(unsafe.Pointer(&header[0]))
-		attrLen := *(*uint32)(unsafe.Pointer(&header[4]))
-		if datOff < 0 || uint32(datOff)+attrLen > uint32(len(dat)) {
-			return attrs, errorspkg.New("truncated results; attrBuf too small")
-		}
-		end := uint32(datOff) + attrLen
-		attrs = append(attrs, dat[datOff:end])
-		i = end
-		if r := i % 4; r != 0 {
-			i += (4 - r)
-		}
-	}
-	return
-}
-
-func libc_getattrlist_trampoline()
-
-//go:linkname libc_getattrlist libc_getattrlist
-//go:cgo_import_dynamic libc_getattrlist getattrlist "/usr/lib/libSystem.B.dylib"
-
 //sysnb pipe(p *[2]int32) (err error)
 
 func Pipe(p []int) (err error) {
@@ -341,6 +259,7 @@ func Kill(pid int, signum Signal) (err error) { return kill(pid, int(signum), 1)
 //sys	fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (val int, err error) = SYS_fcntl
 //sys   unlinkat(fd int, path string, flags int) (err error)
 //sys   openat(fd int, path string, flags int, perm uint32) (fdret int, err error)
+//sys	getcwd(buf []byte) (n int, err error)
 
 func init() {
 	execveDarwin = execve
diff --git a/src/syscall/syscall_getwd_bsd.go b/src/syscall/syscall_getwd_bsd.go
deleted file mode 100644
index b14367936ee8e2044ba42f356d96d68dabe47e22..0000000000000000000000000000000000000000
--- a/src/syscall/syscall_getwd_bsd.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build dragonfly freebsd netbsd openbsd
-
-package syscall
-
-const ImplementsGetwd = true
-
-func Getwd() (string, error) {
-	var buf [pathMax]byte
-	_, err := getcwd(buf[:])
-	if err != nil {
-		return "", err
-	}
-	n := clen(buf[:])
-	if n < 1 {
-		return "", EINVAL
-	}
-	return string(buf[:n]), nil
-}
diff --git a/src/syscall/types_darwin.go b/src/syscall/types_darwin.go
index d8218d6aea168411cad700084de61ea6552b2040..7b3a9d233536e113ca3d355048f23e0b22cbd0c7 100644
--- a/src/syscall/types_darwin.go
+++ b/src/syscall/types_darwin.go
@@ -123,6 +123,12 @@ type Fsid C.struct_fsid
 
 type Dirent C.struct_dirent
 
+// File system limits
+
+const (
+	pathMax = C.PATH_MAX
+)
+
 // Sockets
 
 type RawSockaddrInet4 C.struct_sockaddr_in
diff --git a/src/syscall/zsyscall_darwin_amd64.go b/src/syscall/zsyscall_darwin_amd64.go
index 83214de2fbb0fab7690655e2cea3ae0deda4bc70..093739ebc77e7fa34ed793cbe76c39f049113d35 100644
--- a/src/syscall/zsyscall_darwin_amd64.go
+++ b/src/syscall/zsyscall_darwin_amd64.go
@@ -1943,6 +1943,28 @@ func libc_openat_trampoline()
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func getcwd(buf []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := syscall(funcPC(libc_getcwd_trampoline), uintptr(_p0), uintptr(len(buf)), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+func libc_getcwd_trampoline()
+
+//go:linkname libc_getcwd libc_getcwd
+//go:cgo_import_dynamic libc_getcwd getcwd "/usr/lib/libSystem.B.dylib"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Fstat(fd int, stat *Stat_t) (err error) {
 	_, _, e1 := syscall(funcPC(libc_fstat64_trampoline), uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
diff --git a/src/syscall/zsyscall_darwin_amd64.s b/src/syscall/zsyscall_darwin_amd64.s
index 23ddbe06c0dfff9aa0677e6c74a0931ff33a23f2..d99656d0282da2584b7fa3b1dd1f5bd2f9b121a0 100644
--- a/src/syscall/zsyscall_darwin_amd64.s
+++ b/src/syscall/zsyscall_darwin_amd64.s
@@ -1,8 +1,6 @@
 // go run mkasm_darwin.go amd64
 // Code generated by the command above; DO NOT EDIT.
 #include "textflag.h"
-TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0
-	JMP	libc_getattrlist(SB)
 TEXT ·libc_getfsstat_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_getfsstat(SB)
 TEXT ·libc_setattrlist_trampoline(SB),NOSPLIT,$0-0
@@ -235,6 +233,8 @@ TEXT ·libc_unlinkat_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_unlinkat(SB)
 TEXT ·libc_openat_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_openat(SB)
+TEXT ·libc_getcwd_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_getcwd(SB)
 TEXT ·libc_fstat64_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_fstat64(SB)
 TEXT ·libc_fstatfs64_trampoline(SB),NOSPLIT,$0-0
diff --git a/src/syscall/zsyscall_darwin_arm64.go b/src/syscall/zsyscall_darwin_arm64.go
index 0b7783986925670bb10dacbb564c6b73f03c763b..0ff642eb2542252f2e9cd9b0d578c2fb56350d37 100644
--- a/src/syscall/zsyscall_darwin_arm64.go
+++ b/src/syscall/zsyscall_darwin_arm64.go
@@ -1943,6 +1943,28 @@ func libc_openat_trampoline()
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func getcwd(buf []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := syscall(funcPC(libc_getcwd_trampoline), uintptr(_p0), uintptr(len(buf)), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+func libc_getcwd_trampoline()
+
+//go:linkname libc_getcwd libc_getcwd
+//go:cgo_import_dynamic libc_getcwd getcwd "/usr/lib/libSystem.B.dylib"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Fstat(fd int, stat *Stat_t) (err error) {
 	_, _, e1 := syscall(funcPC(libc_fstat_trampoline), uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
diff --git a/src/syscall/zsyscall_darwin_arm64.s b/src/syscall/zsyscall_darwin_arm64.s
index 7b8b3764a82ac0b0fd4e196c5b1af83a184a2f0a..214851604a2fb4dd246c8e7f4aed4c664aa7b5ed 100644
--- a/src/syscall/zsyscall_darwin_arm64.s
+++ b/src/syscall/zsyscall_darwin_arm64.s
@@ -1,8 +1,6 @@
 // go run mkasm_darwin.go arm64
 // Code generated by the command above; DO NOT EDIT.
 #include "textflag.h"
-TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0
-	JMP	libc_getattrlist(SB)
 TEXT ·libc_getfsstat_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_getfsstat(SB)
 TEXT ·libc_setattrlist_trampoline(SB),NOSPLIT,$0-0
@@ -235,6 +233,8 @@ TEXT ·libc_unlinkat_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_unlinkat(SB)
 TEXT ·libc_openat_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_openat(SB)
+TEXT ·libc_getcwd_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_getcwd(SB)
 TEXT ·libc_fstat_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_fstat(SB)
 TEXT ·libc_fstatfs_trampoline(SB),NOSPLIT,$0-0
diff --git a/src/syscall/ztypes_darwin_amd64.go b/src/syscall/ztypes_darwin_amd64.go
index bbd5bec38584cd7a14ebbdffab3a516e0caaad76..da56f0da22b6a7cbb2fc99243f024ead27e018ac 100644
--- a/src/syscall/ztypes_darwin_amd64.go
+++ b/src/syscall/ztypes_darwin_amd64.go
@@ -151,6 +151,10 @@ type Dirent struct {
 	Pad_cgo_0 [3]byte
 }
 
+const (
+	pathMax = 0x400
+)
+
 type RawSockaddrInet4 struct {
 	Len    uint8
 	Family uint8
diff --git a/src/syscall/ztypes_darwin_arm64.go b/src/syscall/ztypes_darwin_arm64.go
index e9c8549fa1a96954505b8e81450d1cbd38bed441..82685ff6591f92483bb513fda100db6c15f0ce1e 100644
--- a/src/syscall/ztypes_darwin_arm64.go
+++ b/src/syscall/ztypes_darwin_arm64.go
@@ -151,6 +151,10 @@ type Dirent struct {
 	Pad_cgo_0 [3]byte
 }
 
+const (
+	pathMax = 0x400
+)
+
 type RawSockaddrInet4 struct {
 	Len    uint8
 	Family uint8