# SPDX-FileCopyrightText: Huawei Inc.
#
# SPDX-License-Identifier: Apache-2.0

Patch generated from OpenHarmony-v3.1-Release version, with the following commands:

    cp -r porting/linux/user/* .
    git add -A
    git diff --staged > openharmony-linux-user.patch

The hunks from 0001-Make-dynamic-linker-a-relative-symlink-to-libc.patch in
Yocto was removed manually afterwards.

The hunk for the file sys/capabilty.h has been moved to a seperate patch
file so it can be ignored for some configurations that include components
with a dependency on the libcap package, as this pakage already provide
this header.

Upstream-status: Pending
Signed-off-by: Esben Haabendal <esben.haabendal@huawei.com>

diff --git a/arch/arm/bits/fenv.h b/arch/arm/bits/fenv.h
index d85fc86d7947..b497a9878800 100644
--- a/arch/arm/bits/fenv.h
+++ b/arch/arm/bits/fenv.h
@@ -9,10 +9,10 @@
 #define FE_INEXACT    16
 #define FE_ALL_EXCEPT 31
 #define FE_TONEAREST  0
-#define FE_DOWNWARD   0x800000
-#define FE_UPWARD     0x400000
 #define FE_TOWARDZERO 0xc00000
 #endif
+#define FE_DOWNWARD   0x800000
+#define FE_UPWARD     0x400000
 
 typedef unsigned long fexcept_t;
 
diff --git a/arch/generic/bits/shm.h b/arch/generic/bits/shm.h
index 8d19378191ba..da07a2a0cb50 100644
--- a/arch/generic/bits/shm.h
+++ b/arch/generic/bits/shm.h
@@ -1,4 +1,4 @@
-#define SHMLBA 4096
+#define SHMLBA (4*4096)
 
 struct shmid_ds {
 	struct ipc_perm shm_perm;
diff --git a/include/ctype.h b/include/ctype.h
index 7936536f577c..7b91d3ef6228 100644
--- a/include/ctype.h
+++ b/include/ctype.h
@@ -66,6 +66,11 @@ int   toascii(int);
 #define _toupper(a) ((a)&0x5f)
 #define isascii(a) (0 ? isascii(a) : (unsigned)(a) < 128)
 
+#include <stdint.h>
+
+const int32_t **__ctype_tolower_loc(void);
+const int32_t **__ctype_toupper_loc(void);
+
 #endif
 
 #ifdef __cplusplus
diff --git a/include/dlfcn.h b/include/dlfcn.h
index 13ab71dd071e..e87392e70398 100644
--- a/include/dlfcn.h
+++ b/include/dlfcn.h
@@ -24,6 +24,21 @@ char  *dlerror(void);
 void  *dlopen(const char *, int);
 void  *dlsym(void *__restrict, const char *__restrict);
 
+/* namespace apis */
+typedef const char* Dl_namespace;
+
+void dlns_init(Dl_namespace *, const char *);
+
+/* open dso in given namespace which has own lib search paths
+ * when namespace is null, it's same to dlopen() 
+ * void to use "default" as namespace, which is the default namespace*/
+void *dlopen_ns(Dl_namespace *, const char *, int);
+
+/* create the namespace and set lib search paths of namespace,
+ * the paths should be splited by ':'. When namespace already exist, 
+ * return error */
+int dlns_create(Dl_namespace *, const char *);
+
 #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
 typedef struct {
 	const char *dli_fname;
diff --git a/include/pthread.h b/include/pthread.h
index 984db6806418..b430fbffb656 100644
--- a/include/pthread.h
+++ b/include/pthread.h
@@ -6,6 +6,17 @@ extern "C" {
 
 #include <features.h>
 
+/* Musl did not provide the "owner" macro directly,
+ * so users can not access the mutex-ower-ID.
+ * Thus we added this macro for getting the owner-ID
+ * of the mutex. */
+
+/* These macros provides macros for accessing inner
+ * attributes of the pthread_mutex_t struct.
+ * It is intended for solving the coompiling failure
+ * of Dopra codes which claims that .__data.* realm
+ * can not be found in pthread_mutex_t. */
+
 #define __NEED_time_t
 #define __NEED_clockid_t
 #define __NEED_struct_timespec
@@ -78,6 +89,7 @@ int pthread_create(pthread_t *__restrict, const pthread_attr_t *__restrict, void
 int pthread_detach(pthread_t);
 _Noreturn void pthread_exit(void *);
 int pthread_join(pthread_t, void **);
+pid_t pthread_gettid_np(pthread_t);
 
 #ifdef __GNUC__
 __attribute__((const))
diff --git a/include/sys/sysinfo.h b/include/sys/sysinfo.h
index 6a3931e52010..9b095ffb500b 100644
--- a/include/sys/sysinfo.h
+++ b/include/sys/sysinfo.h
@@ -5,6 +5,7 @@
 extern "C" {
 #endif
 
+#ifndef _LINUX_KERNEL_H
 #define SI_LOAD_SHIFT 16
 
 struct sysinfo {
@@ -22,6 +23,7 @@ struct sysinfo {
 	unsigned mem_unit;
 	char __reserved[256];
 };
+#endif
 
 int sysinfo (struct sysinfo *);
 int get_nprocs_conf (void);
diff --git a/include/unistd.h b/include/unistd.h
index 7bcbff943d4a..c9a87b1a14b6 100644
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -190,6 +190,7 @@ int syncfs(int);
 int euidaccess(const char *, int);
 int eaccess(const char *, int);
 ssize_t copy_file_range(int, off_t *, int, off_t *, size_t, unsigned);
+pid_t gettid(void);
 #endif
 
 #if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
@@ -462,6 +463,19 @@ ssize_t copy_file_range(int, off_t *, int, off_t *, size_t, unsigned);
 #define _CS_V6_ENV	1148
 #define _CS_V7_ENV	1149
 
+#ifdef _GNU_SOURCE
+#ifndef TEMP_FAILURE_RETRY
+#define MUSL_TEMP_FAILURE_RETRY(expression) \
+    (__extension__ \
+        ({ long int __result; \
+            do __result = (long int)(expression); \
+            while(__result == -1L&& errno == EINTR); \
+        __result;}))
+
+#define TEMP_FAILURE_RETRY(expression) MUSL_TEMP_FAILURE_RETRY(expression)
+#endif
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index afec985a3dbe..1219ee601a3e 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -32,6 +32,7 @@ static void error(const char *, ...);
 
 #define container_of(p,t,m) ((t*)((char *)(p)-offsetof(t,m)))
 #define countof(a) ((sizeof (a))/(sizeof (a)[0]))
+#define DSO_FLAGS_NODELETE 0x1
 
 struct debug {
 	int ver;
@@ -56,6 +57,9 @@ struct dso {
 	size_t *dynv;
 	struct dso *next, *prev;
 
+	/* mark the dso status */
+	unsigned int flags;
+
 	Phdr *phdr;
 	int phnum;
 	size_t phentsize;
@@ -76,10 +80,12 @@ struct dso {
 	char mark;
 	char bfs_built;
 	char runtime_loaded;
+	char by_dlopen;
 	struct dso **deps, *needed_by;
 	size_t ndeps_direct;
 	size_t next_dep;
 	int ctor_visitor;
+	int nr_dlopen;
 	char *rpath_orig, *rpath;
 	struct tls_module tls;
 	size_t tls_id;
@@ -1021,6 +1027,8 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
 			ldso.prev = tail;
 			tail = &ldso;
 		}
+		/* increase libc dlopen refcnt */
+		a_inc(&ldso.nr_dlopen);
 		return &ldso;
 	}
 	if (strchr(name, '/')) {
@@ -1030,6 +1038,7 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
 		/* Search for the name to see if it's already loaded */
 		for (p=head->next; p; p=p->next) {
 			if (p->shortname && !strcmp(p->shortname, name)) {
+				a_inc(&p->nr_dlopen);
 				return p;
 			}
 		}
@@ -1046,11 +1055,13 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
 			if (!sys_path) {
 				char *prefix = 0;
 				size_t prefix_len;
+				char *filename = ldso.name;
 				if (ldso.name[0]=='/') {
 					char *s, *t, *z;
 					for (s=t=z=ldso.name; *s; s++)
 						if (*s=='/') z=t, t=s;
 					prefix_len = z-ldso.name;
+					filename = t+1;
 					if (prefix_len < PATH_MAX)
 						prefix = ldso.name;
 				}
@@ -1058,11 +1069,12 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
 					prefix = "";
 					prefix_len = 0;
 				}
+				size_t name_len = strchrnul(filename, '.') - filename;
 				char etc_ldso_path[prefix_len + 1
-					+ sizeof "/etc/ld-musl-" LDSO_ARCH ".path"];
+					+ sizeof "/etc/.path" + name_len];
 				snprintf(etc_ldso_path, sizeof etc_ldso_path,
-					"%.*s/etc/ld-musl-" LDSO_ARCH ".path",
-					(int)prefix_len, prefix);
+					"%.*s/etc/%.*s.path",
+					(int)prefix_len, prefix, (int)name_len, filename);
 				FILE *f = fopen(etc_ldso_path, "rbe");
 				if (f) {
 					if (getdelim(&sys_path, (size_t[1]){0}, 0, f) <= 0) {
@@ -1074,7 +1086,7 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
 					sys_path = "";
 				}
 			}
-			if (!sys_path) sys_path = SYS_PATH_DFLT;
+			if (!sys_path) sys_path = strdup(SYS_PATH_DFLT);
 			fd = path_open(name, sys_path, buf, sizeof buf);
 		}
 		pathname = buf;
@@ -1092,6 +1104,8 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
 			if (!p->shortname && pathname != name)
 				p->shortname = strrchr(p->name, '/')+1;
 			close(fd);
+			/* increase dlopen refcnt */
+			a_inc(&p->nr_dlopen);
 			return p;
 		}
 	}
@@ -1137,6 +1151,7 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
 	p->ino = st.st_ino;
 	p->needed_by = needed_by;
 	p->name = p->buf;
+	p->nr_dlopen = 1;
 	p->runtime_loaded = runtime;
 	strcpy(p->name, pathname);
 	/* Add a shortname only if name arg was not an explicit pathname. */
@@ -1166,6 +1181,9 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
 	p->prev = tail;
 	tail = p;
 
+	if (runtime)
+		p->by_dlopen = 1;
+
 	if (DL_FDPIC) makefuncdescs(p);
 
 	if (ldd_mode) dprintf(1, "\t%s => %s (%p)\n", name, pathname, p->base);
@@ -2086,6 +2104,10 @@ void *dlopen(const char *file, int mode)
 	 * relocations resolved to symbol definitions that get removed. */
 	redo_lazy_relocs();
 
+	if (mode & RTLD_NODELETE) {
+		p->flags |= DSO_FLAGS_NODELETE;
+	}
+
 	update_tls_size();
 	if (tls_cnt != orig_tls_cnt)
 		install_new_tls();
@@ -2169,6 +2191,102 @@ static void *do_dlsym(struct dso *p, const char *s, void *ra)
 	return laddr(def.dso, def.sym->st_value);
 }
 
+static int do_dlclose(struct dso *p)
+{
+	int old;
+	size_t n;
+	struct dso *d;
+
+	if (__dl_invalid_handle(p))
+		return -1;
+
+	if (!p->by_dlopen) {
+		error("Library %s is not loaded by dlopen", p->name);
+		return -1;
+	}
+
+	/* dso is marked  as RTLD_NODELETE library, do nothing here. */
+	if ((p->flags & DSO_FLAGS_NODELETE) != 0) {
+		return 0;
+	}
+
+	old = a_fetch_add(&p->nr_dlopen, -1);
+	if (old > 1)
+		return 0;
+
+	/* call destructors if needed */
+	if (p->constructed) {
+		size_t dyn[DYN_CNT];
+		decode_vec(p->dynv, dyn, DYN_CNT);
+		if (dyn[0] & (1<<DT_FINI_ARRAY)) {
+			n = dyn[DT_FINI_ARRAYSZ] / sizeof(size_t);
+			size_t *fn = (size_t *)laddr(p, dyn[DT_FINI_ARRAY]) + n;
+			while (n--)
+				((void (*)(void))*--fn)();
+		}
+		p->constructed = 0;
+	}
+
+	/* remove dso symbols from global list */
+	if (p->syms_next) {
+		for (d = head; d->syms_next != p; d = d->syms_next)
+			; /* NOP */
+		d->syms_next = p->syms_next;
+	} else if (p == syms_tail) {
+		for (d = head; d->syms_next != p; d = d->syms_next)
+			; /* NOP */
+		d->syms_next = NULL;
+		syms_tail = d;
+	}
+
+	/* remove dso from lazy list if needed */
+	if (p == lazy_head) {
+		lazy_head = p->lazy_next;
+	} else if (p->lazy_next) {
+		for (d = lazy_head; d->lazy_next != p; d = d->lazy_next)
+			; /* NOP */
+		d->lazy_next = p->lazy_next;
+	}
+
+	/* remove dso from fini list */
+	if (p == fini_head) {
+		fini_head = p->fini_next;
+	} else if (p->fini_next) {
+		for (d = fini_head; d->fini_next != p; d = d->fini_next)
+			; /* NOP */
+		d->fini_next = p->fini_next;
+	}
+
+	/* remove dso from global dso list */
+	if (p == tail) {
+		tail = p->prev;
+		tail->next = NULL;
+	} else {
+		p->next->prev = p->prev;
+		p->prev->next = p->next;
+	}
+
+	if (p->lazy != NULL)
+		free(p->lazy);
+	if (p->deps != no_deps)
+		free(p->deps);
+	unmap_library(p);
+	free(p);
+
+	return 0;
+}
+
+hidden int __dlclose(void *p)
+{
+	int rc;
+	pthread_rwlock_wrlock(&lock);
+	__inhibit_ptc();
+	rc = do_dlclose(p);
+	__release_ptc();
+	pthread_rwlock_unlock(&lock);
+	return rc;
+}
+
 int dladdr(const void *addr_arg, Dl_info *info)
 {
 	size_t addr = (size_t)addr_arg;
@@ -2312,3 +2430,46 @@ static void error(const char *fmt, ...)
 	__dl_vseterr(fmt, ap);
 	va_end(ap);
 }
+void dlns_init(Dl_namespace *ns, const char *name)
+{
+	*ns = name;
+}
+
+void *dlopen_ns(Dl_namespace *ns, const char *file, int mode)
+{
+	if (!ns) return NULL;
+
+	return dlopen(file, mode);
+}
+
+int dlns_create(Dl_namespace *ns,const char *search_path)
+{
+	int sys_length = 0;
+	int search_length =  0;
+	char * new_path = NULL;
+
+	if (!search_path || !ns) return EINVAL;
+
+	sys_length = strlen(sys_path);
+	search_length = strlen(search_path);
+
+	if (search_path[0] != ':'){
+		sys_length += search_length + 1;
+	} else  {
+		sys_length += search_length;
+	}
+
+	new_path = (char *)malloc(sys_length + 1);
+	if (!new_path) return ENOMEM;
+
+	strcpy(new_path, sys_path);
+	if (search_path[0] != ':') {
+		strcat(new_path, ":");
+	}
+	strcat(new_path, search_path);
+
+	free(sys_path);
+	sys_path = new_path;
+
+	return 0;
+}
diff --git a/src/hook/common_def.h b/src/hook/common_def.h
new file mode 100755
index 000000000000..7d74b3da0c27
--- /dev/null
+++ b/src/hook/common_def.h
@@ -0,0 +1,10 @@
+#ifndef _COMMON_DEF_H
+#define _COMMON_DEF_H
+
+#include <unistd.h>
+#include <stdlib.h>
+
+#define	__predict_true(exp) __builtin_expect((exp) != 0, 1)
+#define	__predict_false(exp) __builtin_expect((exp) != 0, 0)
+
+#endif
\ No newline at end of file
diff --git a/src/hook/malloc_common.c b/src/hook/malloc_common.c
new file mode 100755
index 000000000000..50abc4d5e5d5
--- /dev/null
+++ b/src/hook/malloc_common.c
@@ -0,0 +1,33 @@
+#ifdef HOOK_ENABLE
+#include <unistd.h>
+#include <sys/types.h>
+#include "musl_malloc.h"
+#include <malloc.h>
+#include "musl_malloc_dispatch_table.h"
+#include "common_def.h"
+#include "musl_preinit_common.h"
+
+void* malloc(size_t bytes)
+{
+	volatile const struct MallocDispatchType* dispatch_table = get_current_dispatch_table();
+	if (__predict_false(dispatch_table != NULL)) {
+		void*ret = dispatch_table->malloc(bytes);
+		return ret;
+	}
+	void* result = MuslMalloc(malloc)(bytes);
+	if (__predict_false(result == NULL)) {
+		//__musl_log(__MUSL_LOG_WARN, "malloc(%zu) failed: returning null pointer\n", bytes);
+	}
+	return result;
+}
+
+void free(void* mem)
+{
+	volatile const struct MallocDispatchType* dispatch_table = get_current_dispatch_table();
+	if (__predict_false(dispatch_table != NULL)) {
+		dispatch_table->free(mem);
+	} else {
+		MuslMalloc(free)(mem);
+	}
+}
+#endif
diff --git a/src/hook/musl_malloc.h b/src/hook/musl_malloc.h
new file mode 100755
index 000000000000..27f30869d0d8
--- /dev/null
+++ b/src/hook/musl_malloc.h
@@ -0,0 +1,26 @@
+#ifndef _MUSL_MALLOC_H
+#define _MUSL_MALLOC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HOOK_ENABLE
+#define MuslMalloc(func) __libc_ ## func
+#else
+#define MuslMalloc(func) func
+#endif
+
+void *__libc_malloc(size_t);
+void *__libc_calloc(size_t, size_t);
+void *__libc_realloc(void *, size_t);
+void __libc_free(void *);
+void *__libc_valloc(size_t);
+void *__libc_memalign(size_t, size_t);
+size_t __libc_malloc_usable_size(void *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/musl_malloc_dispatch.h b/include/musl_malloc_dispatch.h
new file mode 100755
index 000000000000..15b859eea083
--- /dev/null
+++ b/include/musl_malloc_dispatch.h
@@ -0,0 +1,37 @@
+#ifndef _MUSL_MALLOC_DISPATCH_H
+#define _MUSL_MALLOC_DISPATCH_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+typedef void* (*MallocMallocType)(size_t);
+typedef void* (*MallocReallocType)(void*, size_t);
+typedef void* (*MallocCallocType)(size_t, size_t);
+typedef void* (*MallocVallocType)(size_t);
+typedef void (*MallocFreeType)(void*);
+typedef void* (*MallocMemalignType)(size_t, size_t);
+typedef size_t (*MallocMallocUsableSizeType)(void*);
+typedef bool (*GetHookFlagType)();
+typedef bool (*SetHookFlagType)(bool);
+
+struct MallocDispatchType {
+	MallocMallocType malloc;
+	MallocCallocType calloc;
+	MallocReallocType realloc;
+	MallocVallocType valloc;
+	MallocFreeType free;
+	MallocMemalignType memalign;
+	MallocMallocUsableSizeType malloc_usable_size;
+	GetHookFlagType get_hook_flag;
+	SetHookFlagType set_hook_flag;
+};
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/musl_malloc_dispatch_table.h b/include/musl_malloc_dispatch_table.h
new file mode 100755
index 000000000000..430de744bb50
--- /dev/null
+++ b/include/musl_malloc_dispatch_table.h
@@ -0,0 +1,13 @@
+#ifndef _MUSL_MALLOC_DISPATCH_TABLE_H
+#define _MUSL_MALLOC_DISPATCH_TABLE_H
+
+#include "musl_malloc_dispatch.h"
+#include <stdatomic.h>
+
+struct musl_libc_globals {
+	volatile atomic_llong current_dispatch_table;
+	volatile atomic_llong so_dispatch_table;
+	struct MallocDispatchType malloc_dispatch_table;
+};
+
+#endif
diff --git a/src/hook/musl_preinit.c b/src/hook/musl_preinit.c
new file mode 100755
index 000000000000..57a0bf12fb84
--- /dev/null
+++ b/src/hook/musl_preinit.c
@@ -0,0 +1,400 @@
+/*
+The hook mode has 3 kinds which can be set by command "param set":
+(1) param set libc.hook_mode "startup:\"prog1 \""
+(2) param set libc.hook_mode startup:program1
+(3) param set libc.hook_mode step
+(4) param set libc.hook_mode direct
+
+Case 1 represents "startup" mode, and the hooked process is "prog1 ",
+which loads hooking shared library when the program starts up.
+The path is added with two quotation marks because a quotation mark is a special charcter,
+which need be escaped.
+(2) is similar with (1), but no escaped character, so quotation marks doesn't need.
+(3) represents "step" mode, which loads hooking shared library by some steps.
+(4) represetnt  "direct" mode, which loads hooking shared library by a step.
+*/
+
+#ifdef HOOK_ENABLE
+#include <unistd.h>
+#include <signal.h>
+#include "musl_malloc_dispatch_table.h"
+#include "musl_malloc.h"
+#include "musl_preinit_common.h"
+#include <pthread.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <dlfcn.h>
+#include <stdatomic.h>
+#include <ctype.h>
+#include <assert.h>
+#include <string.h>
+#include <malloc.h>
+
+void* ohos_malloc_hook_init_function(size_t bytes);
+
+static struct MallocDispatchType __ohos_malloc_hook_init_dispatch = {
+	.malloc = ohos_malloc_hook_init_function,
+	.free = MuslMalloc(free),
+};
+#define MAX_SYM_NAME_SIZE 1000
+static char *__malloc_hook_shared_lib = "libnative_hook.z.so";
+static char *__malloc_hook_function_prefix = "ohos_malloc_hook";
+static char *__get_param_shared_Lib = "libparam_client.z.so";
+volatile atomic_llong ohos_malloc_hook_shared_liibrary;
+void* function_of_shared_lib[LAST_FUNCTION];
+static enum EnumHookMode __hook_mode = STEP_HOOK_MODE;
+static char __hook_process_path[PATH_MAX+ 1] = {0};
+static char __progname[PATH_MAX + 1] = {0};
+
+
+static char* get_native_hook_param()
+{
+	int (*getFunction)(const char *name, char *value, unsigned int *len);
+
+	void* shared_library_handle = dlopen(__get_param_shared_Lib, RTLD_NOW | RTLD_LOCAL);
+	if (!shared_library_handle) {
+		return NULL;
+	}
+
+	getFunction = (int (*)(const char *name, char *value, unsigned int *len))dlsym((void*)shared_library_handle, "SystemGetParameter");
+	if (getFunction == NULL) {
+		dlclose(shared_library_handle);
+		return NULL;
+	}
+	const char *key =  MUSL_HOOK_PARAM_NAME;
+	char *value = (char *)malloc(OHOS_PARAM_MAX_SIZE);
+	memset(value, 0, OHOS_PARAM_MAX_SIZE);
+	if (value == NULL) {
+		dlclose(shared_library_handle);
+		return NULL;
+	}
+	unsigned int len = OHOS_PARAM_MAX_SIZE;
+	getFunction(key, value, &len);
+	dlclose(shared_library_handle);
+	return value;
+}
+
+static int parse_hook_variable(enum EnumHookMode* mode, char* path, int size)
+{
+	if (!mode || !path || size <= 0) {
+		return -1;
+	}
+
+	bool flag = __set_hook_flag(false);
+	char* hook_param_value = get_native_hook_param();
+	if (!hook_param_value) {
+		*mode = STEP_HOOK_MODE;
+		path[0] = '\0';
+	} else {
+		char* ptr = hook_param_value;
+		char* mode_str = hook_param_value;
+
+		while (*ptr && *ptr != ':') {
+			++ptr;
+		}
+
+		if (*ptr == ':') {
+			*ptr = '\0';
+			++ptr;
+		}
+
+		if (strcmp(mode_str, "startup") == 0) {
+			*mode = STATRUP_HOOK_MODE;
+		} else if (strcmp(mode_str, "direct") == 0) {
+			*mode = DIRECT_HOOK_MODE;
+		} else if (strcmp(mode_str, "step") == 0) {
+			*mode = STEP_HOOK_MODE;
+		} else {
+			*mode = STEP_HOOK_MODE;
+		}
+		if (*mode == STATRUP_HOOK_MODE) {
+			if (*ptr == '\"') {
+				++ptr;
+				int idx = 0;
+				while (idx < size - 1 && *ptr && *ptr != '\"') {
+					path[idx++] = *ptr++;
+				}
+				path[idx] = '\0';
+			} else {
+				int idx = 0;
+				while (idx < size - 1 && *ptr) {
+					path[idx++] = *ptr++;
+				}
+				path[idx] = '\0';
+			}
+		}
+
+		free(hook_param_value);
+	}
+	__set_hook_flag(flag);
+	return 0;
+}
+
+static bool init_malloc_function(void* malloc_shared_library_handler, MallocMallocType* func, const char* prefix)
+{
+	char symbol[MAX_SYM_NAME_SIZE];
+	snprintf(symbol, sizeof(symbol), "%s_%s", prefix, "malloc");
+	*func = (MallocMallocType)(dlsym(malloc_shared_library_handler, symbol));
+	if (*func == NULL) {
+		return false;
+	}
+	return true;
+}
+
+static bool init_free_function(void* malloc_shared_library_handler, MallocFreeType* func, const char* prefix)
+{
+	char symbol[MAX_SYM_NAME_SIZE];
+	snprintf(symbol, sizeof(symbol), "%s_%s", prefix, "free");
+	*func = (MallocFreeType)(dlsym(malloc_shared_library_handler, symbol));
+	if (*func == NULL) {
+		return false;
+	}
+	return true;
+}
+
+static bool init_hook_functions(void* shared_library_handler, struct MallocDispatchType* table, const char* prefix)
+{
+	if (!init_malloc_function(shared_library_handler, &table->malloc, prefix)) {
+		return false;
+	}
+	if (!init_free_function(shared_library_handler, &table->free, prefix)) {
+		return false;
+	}
+	return true;
+}
+
+static void clear_function_table()
+{
+	for (size_t i = 0; i < LAST_FUNCTION; i++) {
+		function_of_shared_lib[i] = NULL;
+	}
+}
+
+bool init_malloc_hook_shared_library(void* shared_library_handle, const char* shared_lib, const char* prefix, struct MallocDispatchType* dispatch_table)
+{
+	static const char* names[] = {
+		"initialize",
+		"finalize",
+		"get_hook_flag",
+		"set_hook_flag",
+		"on_start",
+		"on_end",
+	};
+
+	for (int i = 0; i < LAST_FUNCTION; i++) {
+		char symbol[MAX_SYM_NAME_SIZE];
+		snprintf(symbol, sizeof(symbol), "%s_%s", prefix, names[i]);
+		function_of_shared_lib[i] = dlsym(shared_library_handle, symbol);
+		if (function_of_shared_lib[i] == NULL) {
+			// __musl_log(__MUSL_LOG_ERROR, "%s: %s routine not found in %s\n", getprogname(), symbol, shared_lib);
+			clear_function_table();
+			return false;
+		}
+	}
+
+	if (!init_hook_functions(shared_library_handle, dispatch_table, prefix)) {
+		clear_function_table();
+		return false;
+	}
+
+	return true;
+}
+
+void* load_malloc_hook_shared_library(const char* shared_lib, const char* prefix, struct MallocDispatchType* dispatch_table)
+{
+	void* shared_library_handle = NULL;
+
+	shared_library_handle = dlopen(shared_lib, RTLD_NOW | RTLD_LOCAL);
+
+	if (shared_library_handle == NULL) {
+		printf("Unable to open shared library %s: %s\n", shared_lib, dlerror());
+		return NULL;
+	}
+
+	if (!init_malloc_hook_shared_library(shared_library_handle, shared_lib, prefix, dispatch_table)) {
+		dlclose(shared_library_handle);
+		shared_library_handle = NULL;
+	}
+	// printf("load_malloc_hook_shared_library success new version test\n");
+	return shared_library_handle;
+}
+
+typedef void (*finalize_func_t)();
+typedef bool (*init_func_t)(const struct MallocDispatchType*, bool*, const char*);
+typedef bool (*on_start_func_t)();
+typedef bool (*on_end_func_t)();
+
+static void malloc_finalize()
+{
+	__set_hook_flag(false);
+	((finalize_func_t)function_of_shared_lib[FINALIZE_FUNCTION])();
+
+	fclose(stdin);
+	fclose(stdout);
+	fclose(stderr);
+}
+
+bool finish_install_ohos_malloc_hooks(struct musl_libc_globals* globals, const char* options, const char* prefix)
+{
+	init_func_t init_func = (init_func_t)(function_of_shared_lib[INITIALIZE_FUNCTION]);
+	if (!init_func(&__libc_malloc_default_dispatch, NULL, options)) {
+		// __musl_log(__MUSL_LOG_ERROR, "%s: failed to enable malloc %s\n", getprogname(), prefix);
+		clear_function_table();
+		return false;
+	}
+	on_start_func_t start_func = (on_start_func_t)(function_of_shared_lib[ON_START_FUNCTION]);
+	if (!start_func()) {
+		// __musl_log(__MUSL_LOG_ERROR, "%s: failed to start %s\n", getprogname(), prefix);
+		clear_function_table();
+		return false;
+	}
+	atomic_store_explicit(&__musl_libc_globals.so_dispatch_table, (volatile long long)&globals->malloc_dispatch_table, memory_order_seq_cst);
+	atomic_store_explicit(&__musl_libc_globals.current_dispatch_table, (volatile long long)&globals->malloc_dispatch_table, memory_order_seq_cst);
+
+	int ret_value = atexit(malloc_finalize);
+	if (ret_value != 0) {
+		// __musl_log(__MUSL_LOG_ERROR, "failed to set atexit cleanup function: %d\n", ret_value);
+	}
+	return true;
+}
+
+static bool is_empty_string(const char* str)
+{
+	while (*str) {
+		if (!isspace((unsigned char)(*str))) {
+			return false;
+		}
+	}
+	return true;
+}
+
+static void install_ohos_malloc_hook(struct musl_libc_globals* globals)
+{
+	volatile void* shared_library_handle = (volatile void *)atomic_load_explicit(&ohos_malloc_hook_shared_liibrary, memory_order_acquire);
+	assert(shared_library_handle == NULL || shared_library_handle == (volatile void*)-1);
+	shared_library_handle = (volatile void*)load_malloc_hook_shared_library(__malloc_hook_shared_lib, __malloc_hook_function_prefix, &globals->malloc_dispatch_table);
+	if (shared_library_handle == NULL) {
+		// __musl_log(__MUSL_LOG_ERROR, "Can't load shared library '%s'\n", __malloc_hook_shared_lib);
+		return;
+	}
+
+	if (finish_install_ohos_malloc_hooks(globals, NULL, __malloc_hook_function_prefix)) {
+		atomic_store_explicit(&ohos_malloc_hook_shared_liibrary, (volatile long long)shared_library_handle, memory_order_seq_cst);
+	} else {
+		// __musl_log(__MUSL_LOG_ERROR, "finish_install_ohos_malloc_hooks failed\n");
+		dlclose((void *)shared_library_handle);
+		atomic_store_explicit(&ohos_malloc_hook_shared_liibrary, (volatile long long)0, memory_order_seq_cst);
+	}
+}
+
+static void* init_ohos_malloc_hook()
+{
+	bool flag = __set_hook_flag(false);
+	install_ohos_malloc_hook(&__musl_libc_globals);
+	__set_hook_flag(flag);
+	return NULL;
+}
+
+void* ohos_malloc_hook_init_function(size_t bytes)
+{
+	if (atomic_exchange(&__musl_libc_globals.current_dispatch_table, (volatile const long long)NULL)) {
+		pthread_t thread_id;
+		if (pthread_create(&thread_id, NULL, init_ohos_malloc_hook, NULL) != 0) {
+			// __musl_log(__MUSL_LOG_ERROR, "%s: ohos_malloc_hook: failed to pthread_create\n", getprogname());
+		} else if (pthread_detach(thread_id) != 0) {
+			// __musl_log(__MUSL_LOG_ERROR, "%s: ohos_malloc_hook: failed to pthread_detach\n", getprogname());
+		}
+	}
+	void*ptr = MuslMalloc(malloc)(bytes);
+	return ptr;
+
+}
+
+static void __set_default_malloc()
+{
+	atomic_store_explicit(&__musl_libc_globals.current_dispatch_table, (volatile const long long)NULL, memory_order_seq_cst);
+}
+
+static void __install_malloc_hook()
+{
+	atomic_store_explicit(&__hook_enable_hook_flag, (volatile bool)true, memory_order_seq_cst);
+
+	volatile void* shared_library_handle = (volatile void* )atomic_load_explicit(&ohos_malloc_hook_shared_liibrary, memory_order_acquire);
+	if (shared_library_handle == NULL) {
+		if (__hook_mode == STEP_HOOK_MODE) {
+			atomic_store_explicit(&__musl_libc_globals.current_dispatch_table, (volatile const long long)&__ohos_malloc_hook_init_dispatch, memory_order_seq_cst);
+			atomic_store_explicit(&ohos_malloc_hook_shared_liibrary, (volatile long long)-1, memory_order_seq_cst);
+		} else {
+			init_ohos_malloc_hook();
+		}
+	} else if (shared_library_handle != (void*)-1) {
+		bool flag = __set_hook_flag(false);
+		on_start_func_t start_func = (on_start_func_t)(function_of_shared_lib[ON_START_FUNCTION]);
+		if (start_func && !start_func()) {
+			// __musl_log(__MUSL_LOG_ERROR, "%s: failed to enable malloc\n", getprogname());
+		}
+		__set_hook_flag(flag);
+		volatile const struct MallocDispatchType* so_dispatch_value = (volatile const struct MallocDispatchType* )atomic_load_explicit(&__musl_libc_globals.so_dispatch_table, memory_order_acquire);
+		atomic_store_explicit(&__musl_libc_globals.current_dispatch_table, (volatile long long)so_dispatch_value, memory_order_seq_cst);
+	}
+}
+
+static void __uninstal_malloc_hook()
+{
+	atomic_store_explicit(&__hook_enable_hook_flag, (volatile bool)false, memory_order_seq_cst);
+
+	bool flag = __set_hook_flag(false);
+	__set_default_malloc();
+	on_end_func_t end_func = (on_end_func_t)(function_of_shared_lib[ON_END_FUNCTION]);
+	if (end_func) {
+		end_func();
+	}
+	__set_hook_flag(flag);
+}
+
+static void __install_malloc_hook_signal_handler()
+{
+	struct sigaction actionInstallHook = {};
+	actionInstallHook.sa_handler = __install_malloc_hook;
+	sigemptyset(&actionInstallHook.sa_mask);
+	sigaddset(&actionInstallHook.sa_mask, SIGUNHOOK);
+	sigaction(SIGHOOK, &actionInstallHook, NULL);
+
+	struct sigaction actionDef = {};
+	actionDef.sa_handler = __uninstal_malloc_hook;
+	sigemptyset(&actionDef.sa_mask);
+	sigaddset(&actionDef.sa_mask, SIGHOOK);
+	sigaction(SIGUNHOOK, &actionDef, NULL);
+}
+
+static void __initialize_malloc()
+{
+	__install_malloc_hook_signal_handler();
+}
+
+
+__attribute__((constructor(1))) static void __musl_initialize()
+{
+	atomic_store_explicit(&__hook_enable_hook_flag, (volatile bool)false, memory_order_seq_cst);
+	__set_default_malloc();
+	//__init_musl_log();
+	parse_hook_variable(&__hook_mode, __hook_process_path, sizeof(__hook_process_path));
+	if (__hook_mode == STATRUP_HOOK_MODE) {
+		readlink("/proc/self/exe", __progname, sizeof(__progname) - 1);
+		const char *pos = strrchr(__progname, '/');
+		const char* filename;
+		if (pos) {
+			filename = pos + 1;
+		} else {
+			filename = __progname;
+		}
+		if (strcmp(filename, __hook_process_path) == 0) {
+			atomic_store_explicit(&__hook_enable_hook_flag, (volatile bool)true, memory_order_seq_cst);
+			init_ohos_malloc_hook();
+		} else {
+			__hook_mode = STEP_HOOK_MODE;
+		}
+	}
+	__initialize_malloc();
+}
+#endif
diff --git a/src/hook/musl_preinit_common.c b/src/hook/musl_preinit_common.c
new file mode 100755
index 000000000000..7db57bc0223d
--- /dev/null
+++ b/src/hook/musl_preinit_common.c
@@ -0,0 +1,17 @@
+#ifdef HOOK_ENABLE
+#include "musl_preinit_common.h"
+#include "musl_malloc.h"
+#include <stdatomic.h>
+#include <malloc.h>
+#include <stdlib.h>
+
+struct musl_libc_globals __musl_libc_globals;
+
+struct MallocDispatchType __libc_malloc_default_dispatch = {
+	.malloc = MuslMalloc(malloc),
+	.free = MuslMalloc(free),
+};
+
+volatile atomic_bool __hook_enable_hook_flag;
+
+#endif
diff --git a/include/musl_preinit_common.h b/include/musl_preinit_common.h
new file mode 100755
index 000000000000..b3920f58bd94
--- /dev/null
+++ b/include/musl_preinit_common.h
@@ -0,0 +1,99 @@
+#ifndef _MUSL_PREINIT_COMMON_H
+#define _MUSL_PREINIT_COMMON_H
+
+#include <stdatomic.h>
+#include "musl_malloc_dispatch_table.h"
+#include "musl_malloc_dispatch.h"
+
+extern struct musl_libc_globals __musl_libc_globals;
+
+extern struct MallocDispatchType __libc_malloc_default_dispatch;
+
+extern volatile atomic_bool __hook_enable_hook_flag;
+
+enum EnumFunc {
+	INITIALIZE_FUNCTION,
+	FINALIZE_FUNCTION,
+	GET_HOOK_FLAG_FUNCTION,
+	SET_HOOK_FLAG_FUNCTION,
+	ON_START_FUNCTION,
+	ON_END_FUNCTION,
+	LAST_FUNCTION,
+};
+
+enum EnumHookMode {
+	STATRUP_HOOK_MODE,
+	DIRECT_HOOK_MODE,
+	STEP_HOOK_MODE,
+};
+
+extern void* function_of_shared_lib[];
+extern volatile atomic_llong ohos_malloc_hook_shared_liibrary;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+__attribute__((always_inline))
+inline bool __get_global_hook_flag()
+{
+	volatile bool g_flag = atomic_load_explicit(&__hook_enable_hook_flag, memory_order_acquire);
+	return g_flag;
+}
+
+__attribute__((always_inline))
+inline bool __get_hook_flag()
+{
+	volatile void* impl_handle = (void *)atomic_load_explicit(&ohos_malloc_hook_shared_liibrary, memory_order_acquire);
+	if (impl_handle == NULL) {
+		return false;
+	}
+	else if (impl_handle == (void *)-1) {
+		return true;
+	}
+	else {
+		GetHookFlagType get_hook_func_ptr = (GetHookFlagType)(function_of_shared_lib[GET_HOOK_FLAG_FUNCTION]);
+		bool flag = get_hook_func_ptr();
+		return flag;
+	}
+}
+
+__attribute__((always_inline))
+inline bool __set_hook_flag(bool flag)
+{
+	volatile void* impl_handle = (void *)atomic_load_explicit(&ohos_malloc_hook_shared_liibrary, memory_order_acquire);
+	if (impl_handle == NULL) {
+		return false;
+	}
+	else if (impl_handle == (void *)-1) {
+		return true;
+	}
+	else {
+		SetHookFlagType set_hook_func_ptr = (SetHookFlagType)(function_of_shared_lib[SET_HOOK_FLAG_FUNCTION]);
+		return set_hook_func_ptr(flag);
+	}
+}
+
+__attribute__((always_inline))
+inline volatile const struct MallocDispatchType* get_current_dispatch_table()
+{
+	volatile const struct MallocDispatchType* ret = (struct MallocDispatchType *)atomic_load_explicit(&__musl_libc_globals.current_dispatch_table, memory_order_acquire);
+	if (ret != NULL) {
+		if (!__get_global_hook_flag()) {
+			ret = NULL;
+		}
+		else if (!__get_hook_flag()) {
+			ret = NULL;
+		}
+	}
+	return ret;
+}
+
+#define MUSL_HOOK_PARAM_NAME "libc.hook_mode"
+#define OHOS_PARAM_MAX_SIZE 96
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/internal/dynlink.h b/src/internal/dynlink.h
index 764e3a1a8fa9..6b9492753595 100644
--- a/src/internal/dynlink.h
+++ b/src/internal/dynlink.h
@@ -98,6 +98,7 @@ struct fdpic_dummy_loadmap {
 typedef void (*stage2_func)(unsigned char *, size_t *);
 
 hidden void *__dlsym(void *restrict, const char *restrict, void *restrict);
+hidden int __dlclose(void *p);
 
 hidden void __dl_seterr(const char *, ...);
 hidden int __dl_invalid_handle(void *);
diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h
index 5742dfc55cb9..816cfa7dbe99 100644
--- a/src/internal/pthread_impl.h
+++ b/src/internal/pthread_impl.h
@@ -75,12 +75,22 @@ struct __timer {
 #define _a_sched __u.__i[3*__SU+1]
 #define _a_policy __u.__i[3*__SU+2]
 #define _a_prio __u.__i[3*__SU+3]
+
+/* we define the original value of _m_* in include/pthread.h
+ * as macros MUTEX_* to make the user be able to
+ * access the inner attribute of the mutex struct.
+ * Then, we modify the value of _m_* macros to MUTEX_* here,
+ * so that we can immediately be aware of the changes that
+ * the open source society has made to these original macros,
+ * because patching will fail if the value of the _m_* are
+ * changed by musl society */
 #define _m_type __u.__i[0]
 #define _m_lock __u.__vi[1]
 #define _m_waiters __u.__vi[2]
 #define _m_prev __u.__p[3]
 #define _m_next __u.__p[4]
 #define _m_count __u.__i[5]
+
 #define _c_shared __u.__p[0]
 #define _c_seq __u.__vi[2]
 #define _c_waiters __u.__vi[3]
@@ -173,6 +183,7 @@ hidden void __inhibit_ptc(void);
 hidden void __tl_lock(void);
 hidden void __tl_unlock(void);
 hidden void __tl_sync(pthread_t);
+hidden struct pthread* __pthread_list_find(pthread_t, const char*);
 
 extern hidden volatile int __thread_list_lock;
 
diff --git a/src/internal/syscall.h b/src/internal/syscall.h
index 975a0031d4fb..fb64c282263d 100644
--- a/src/internal/syscall.h
+++ b/src/internal/syscall.h
@@ -278,10 +278,6 @@ hidden long __syscall_ret(unsigned long),
 #define SYS_utimensat SYS_utimensat_time64
 #endif
 
-#ifndef SYS_pselect6
-#define SYS_pselect6 SYS_pselect6_time64
-#endif
-
 #ifndef SYS_ppoll
 #define SYS_ppoll SYS_ppoll_time64
 #endif
diff --git a/src/ldso/dlclose.c b/src/ldso/dlclose.c
index e437422a675a..566c8c3b61aa 100644
--- a/src/ldso/dlclose.c
+++ b/src/ldso/dlclose.c
@@ -1,7 +1,14 @@
 #include <dlfcn.h>
 #include "dynlink.h"
 
-int dlclose(void *p)
+static int dummy(void *p)
 {
 	return __dl_invalid_handle(p);
 }
+weak_alias(dummy, __dlclose);
+
+int dlclose(void *p)
+{
+	return __dlclose(p);
+}
+
diff --git a/src/legacy/ulimit.c b/src/legacy/ulimit.c
index 1f59e8e619f5..d1620e6e2812 100644
--- a/src/legacy/ulimit.c
+++ b/src/legacy/ulimit.c
@@ -1,6 +1,7 @@
 #include <sys/resource.h>
 #include <ulimit.h>
 #include <stdarg.h>
+#include <limits.h>
 
 long ulimit(int cmd, ...)
 {
@@ -15,5 +16,5 @@ long ulimit(int cmd, ...)
 		rl.rlim_cur = 512ULL * val;
 		if (setrlimit(RLIMIT_FSIZE, &rl)) return -1;
 	}
-	return rl.rlim_cur / 512;
+	return rl.rlim_cur == RLIM_INFINITY? LONG_MAX : rl.rlim_cur / 512;
 }
diff --git a/src/linux/gettid.c b/src/linux/gettid.c
new file mode 100644
index 000000000000..70767137e92f
--- /dev/null
+++ b/src/linux/gettid.c
@@ -0,0 +1,8 @@
+#define _GNU_SOURCE
+#include <unistd.h>
+#include "pthread_impl.h"
+
+pid_t gettid(void)
+{
+	return __pthread_self()->tid;
+}
diff --git a/src/malloc/malloc.c b/src/malloc/malloc.c
index 51fa4a3ac399..45a1a936bac5 100644
--- a/src/malloc/malloc.c
+++ b/src/malloc/malloc.c
@@ -9,11 +9,17 @@
 #include "atomic.h"
 #include "pthread_impl.h"
 #include "malloc_impl.h"
+#include <sys/prctl.h>
 
 #if defined(__GNUC__) && defined(__PIC__)
 #define inline inline __attribute__((always_inline))
 #endif
 
+#ifdef HOOK_ENABLE
+void *__libc_malloc(size_t);
+void __libc_free(void *p);
+#endif
+
 static struct {
 	volatile uint64_t binmap;
 	struct bin bins[64];
@@ -281,7 +287,11 @@ static void trim(struct chunk *self, size_t n)
 	__bin_chunk(split);
 }
 
+#ifdef HOOK_ENABLE
+void *__libc_malloc(size_t n)
+#else
 void *malloc(size_t n)
+#endif
 {
 	struct chunk *c;
 	int i, j;
@@ -376,6 +386,10 @@ void *realloc(void *p, size_t n)
 	void *new;
 
 	if (!p) return malloc(n);
+	if (!n) {
+		free(p);
+		return NULL;
+	}
 
 	if (adjust_size(&n) < 0) return 0;
 
@@ -519,7 +533,11 @@ static void unmap_chunk(struct chunk *self)
 	__munmap(base, len);
 }
 
+#ifdef HOOK_ENABLE
+void __libc_free(void *p)
+#else
 void free(void *p)
+#endif
 {
 	if (!p) return;
 
diff --git a/src/multibyte/wcsnrtombs.c b/src/multibyte/wcsnrtombs.c
index 676932b5dcaa..95e25e708dd9 100644
--- a/src/multibyte/wcsnrtombs.c
+++ b/src/multibyte/wcsnrtombs.c
@@ -1,41 +1,33 @@
 #include <wchar.h>
+#include <limits.h>
+#include <string.h>
 
 size_t wcsnrtombs(char *restrict dst, const wchar_t **restrict wcs, size_t wn, size_t n, mbstate_t *restrict st)
 {
-	size_t l, cnt=0, n2;
-	char *s, buf[256];
 	const wchar_t *ws = *wcs;
-	const wchar_t *tmp_ws;
-
-	if (!dst) s = buf, n = sizeof buf;
-	else s = dst;
-
-	while ( ws && n && ( (n2=wn)>=n || n2>32 ) ) {
-		if (n2>=n) n2=n;
-		tmp_ws = ws;
-		l = wcsrtombs(s, &ws, n2, 0);
-		if (!(l+1)) {
-			cnt = l;
-			n = 0;
+	size_t cnt = 0;
+	if (!dst) n=0;
+	while (ws && wn) {
+		char tmp[MB_LEN_MAX];
+		size_t l = wcrtomb(n<MB_LEN_MAX ? tmp : dst, *ws, 0);
+		if (l==-1) {
+			cnt = -1;
 			break;
 		}
-		if (s != buf) {
-			s += l;
+		if (dst) {
+			if (n<MB_LEN_MAX) {
+				if (l>n) break;
+				memcpy(dst, tmp, l);
+			}
+			dst += l;
 			n -= l;
 		}
-		wn = ws ? wn - (ws - tmp_ws) : 0;
-		cnt += l;
-	}
-	if (ws) while (n && wn) {
-		l = wcrtomb(s, *ws, 0);
-		if ((l+1)<=1) {
-			if (!l) ws = 0;
-			else cnt = l;
+		if (!*ws) {
+			ws = 0;
 			break;
 		}
-		ws++; wn--;
-		/* safe - this loop runs fewer than sizeof(buf) times */
-		s+=l; n-=l;
+		ws++;
+		wn--;
 		cnt += l;
 	}
 	if (dst) *wcs = ws;
diff --git a/src/network/inet_legacy.c b/src/network/inet_legacy.c
index 621b47b05086..6d91b6e179f6 100644
--- a/src/network/inet_legacy.c
+++ b/src/network/inet_legacy.c
@@ -12,12 +12,12 @@ struct in_addr inet_makeaddr(in_addr_t n, in_addr_t h)
 	if (n < 256) h |= n<<24;
 	else if (n < 65536) h |= n<<16;
 	else h |= n<<8;
-	return (struct in_addr){ h };
+	return (struct in_addr){ htonl(h) };
 }
 
 in_addr_t inet_lnaof(struct in_addr in)
 {
-	uint32_t h = in.s_addr;
+	uint32_t h = ntohl(in.s_addr);
 	if (h>>24 < 128) return h & 0xffffff;
 	if (h>>24 < 192) return h & 0xffff;
 	return h & 0xff;
@@ -25,7 +25,7 @@ in_addr_t inet_lnaof(struct in_addr in)
 
 in_addr_t inet_netof(struct in_addr in)
 {
-	uint32_t h = in.s_addr;
+	uint32_t h = ntohl(in.s_addr);
 	if (h>>24 < 128) return h >> 24;
 	if (h>>24 < 192) return h >> 16;
 	return h >> 8;
diff --git a/src/passwd/getspnam_r.c b/src/passwd/getspnam_r.c
index 541e85314d56..e738d656cfb7 100644
--- a/src/passwd/getspnam_r.c
+++ b/src/passwd/getspnam_r.c
@@ -15,8 +15,15 @@
 static long xatol(char **s)
 {
 	long x;
+	int sign;
 	if (**s == ':' || **s == '\n') return -1;
+
+	sign = (int)(unsigned char)**s;
+	if (sign == '-' || sign == '+') ++*s;
+
 	for (x=0; **s-'0'<10U; ++*s) x=10*x+(**s-'0');
+
+	if (sign == '-') return -x;
 	return x;
 }
 
diff --git a/src/sched/sched_getparam.c b/src/sched/sched_getparam.c
index 76f10e49d987..b31f00892ef2 100644
--- a/src/sched/sched_getparam.c
+++ b/src/sched/sched_getparam.c
@@ -1,8 +1,20 @@
-#include <sched.h>
-#include <errno.h>
-#include "syscall.h"
-
-int sched_getparam(pid_t pid, struct sched_param *param)
-{
-	return __syscall_ret(-ENOSYS);
-}
+#include <sched.h>
+#include <errno.h>
+#include "syscall.h"
+#include <string.h>
+
+int sched_getparam(pid_t pid, struct sched_param *param)
+{
+	int r;
+	if (!param) {
+		r = -EINVAL;
+		goto exit;
+	}
+	memset(param, 0, sizeof(struct sched_param));
+	r = __syscall(SYS_sched_getparam, pid , param);
+	if (r >= 0) {
+		r = 0;
+	}
+exit:
+	return __syscall_ret(r);
+}
diff --git a/src/sched/sched_getscheduler.c b/src/sched/sched_getscheduler.c
index 394e508b467c..454ac8bcec16 100644
--- a/src/sched/sched_getscheduler.c
+++ b/src/sched/sched_getscheduler.c
@@ -1,8 +1,9 @@
-#include <sched.h>
-#include <errno.h>
-#include "syscall.h"
-
-int sched_getscheduler(pid_t pid)
-{
-	return __syscall_ret(-ENOSYS);
-}
+#include <sched.h>
+#include <errno.h>
+#include "syscall.h"
+
+int sched_getscheduler(pid_t pid)
+{
+	int r = __syscall(SYS_sched_getscheduler, pid);
+	return  __syscall_ret(r);
+}
\ No newline at end of file
diff --git a/src/sched/sched_setparam.c b/src/sched/sched_setparam.c
index 18623ee49b15..2e0f79bff69d 100644
--- a/src/sched/sched_setparam.c
+++ b/src/sched/sched_setparam.c
@@ -1,8 +1,15 @@
-#include <sched.h>
-#include <errno.h>
-#include "syscall.h"
-
-int sched_setparam(pid_t pid, const struct sched_param *param)
-{
-	return __syscall_ret(-ENOSYS);
-}
+#include <sched.h>
+#include <errno.h>
+#include "syscall.h"
+
+int sched_setparam(pid_t pid, const struct sched_param *param)
+{
+	int r;
+	if (!param) {
+		r = -EINVAL;
+		goto exit;
+	}
+	r = __syscall(SYS_sched_setparam, pid, param);
+exit:
+	return __syscall_ret(r);
+}
\ No newline at end of file
diff --git a/src/sched/sched_setscheduler.c b/src/sched/sched_setscheduler.c
index 4435f2164671..fcb5873f59b1 100644
--- a/src/sched/sched_setscheduler.c
+++ b/src/sched/sched_setscheduler.c
@@ -4,5 +4,12 @@
 
 int sched_setscheduler(pid_t pid, int sched, const struct sched_param *param)
 {
-	return __syscall_ret(-ENOSYS);
-}
+	int r;
+	if (!param) {
+		r = -EINVAL;
+		goto exit;
+	}
+	r = __syscall(SYS_sched_setscheduler, pid , sched , param);
+exit:
+	return __syscall_ret(r);
+}
\ No newline at end of file
diff --git a/src/thread/arm/clone.s b/src/thread/arm/clone.s
index bb0965dafe82..2070dd51bd27 100644
--- a/src/thread/arm/clone.s
+++ b/src/thread/arm/clone.s
@@ -3,8 +3,14 @@
 .global __clone
 .hidden __clone
 .type   __clone,%function
+.cfi_startproc
 __clone:
 	stmfd sp!,{r4,r5,r6,r7}
+	.cfi_def_cfa_offset 16
+	.cfi_rel_offset r4, 0
+	.cfi_rel_offset r5, 4
+	.cfi_rel_offset r6, 8
+	.cfi_rel_offset r7, 12
 	mov r7,#120
 	mov r6,r3
 	mov r5,r0
@@ -17,6 +23,7 @@ __clone:
 	tst r0,r0
 	beq 1f
 	ldmfd sp!,{r4,r5,r6,r7}
+	.cfi_def_cfa_offset 0
 	bx lr
 
 1:	mov r0,r6
@@ -26,3 +33,4 @@ __clone:
 	b 2b
 
 3:	bx r5
+.cfi_endproc
\ No newline at end of file
diff --git a/src/thread/arm/syscall_cp.s b/src/thread/arm/syscall_cp.s
index e607dd426afc..03a83dc952b9 100644
--- a/src/thread/arm/syscall_cp.s
+++ b/src/thread/arm/syscall_cp.s
@@ -7,11 +7,16 @@
 .hidden __cp_cancel
 .hidden __cancel
 .global __syscall_cp_asm
-.hidden __syscall_cp_asm
 .type __syscall_cp_asm,%function
+.cfi_startproc
 __syscall_cp_asm:
 	mov ip,sp
 	stmfd sp!,{r4,r5,r6,r7}
+	.cfi_def_cfa_offset 16
+	.cfi_rel_offset r4, 0
+	.cfi_rel_offset r5, 4
+	.cfi_rel_offset r6, 8
+	.cfi_rel_offset r7, 12
 __cp_begin:
 	ldr r0,[r0]
 	cmp r0,#0
@@ -23,7 +28,10 @@ __cp_begin:
 	svc 0
 __cp_end:
 	ldmfd sp!,{r4,r5,r6,r7}
+	.cfi_def_cfa_offset 0
 	bx lr
 __cp_cancel:
 	ldmfd sp!,{r4,r5,r6,r7}
+	.cfi_def_cfa_offset 0
 	b __cancel
+.cfi_endproc