netsurf: branch master updated. release/3.10-303-g0718e58
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/0718e5868119c9f61a6c6...
...commit http://git.netsurf-browser.org/netsurf.git/commit/0718e5868119c9f61a6c6f1...
...tree http://git.netsurf-browser.org/netsurf.git/tree/0718e5868119c9f61a6c6f1fe...
The branch, master has been updated
via 0718e5868119c9f61a6c6f1fe11de21ff6ba9b9a (commit)
via 41f0a5a36ecc6381880bd19b4f6838ac22f7d833 (commit)
from 1810fbfe22a1202ddbd8024dde4ec10882cc3e76 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=0718e5868119c9f61a6...
commit 0718e5868119c9f61a6c6f1fe11de21ff6ba9b9a
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
utils: Use fstatat and unlinkat if supported
diff --git a/utils/config.h b/utils/config.h
index 0227f41..f54326d 100644
--- a/utils/config.h
+++ b/utils/config.h
@@ -146,6 +146,15 @@ char *realpath(const char *path, char *resolved_path);
#undef HAVE_SCANDIR
#endif
+#define HAVE_DIRFD
+#define HAVE_UNLINKAT
+#define HAVE_FSTATAT
+#if (defined(_WIN32) || defined(__riscos__) || defined(__HAIKU__) || defined(__BEOS__) || defined(__amigaos4__) || defined(__AMIGA__) || defined(__MINT__))
+#undef HAVE_DIRFD
+#undef HAVE_UNLINKAT
+#undef HAVE_FSTATAT
+#endif
+
#define HAVE_REGEX
#if (defined(__serenity__))
#undef HAVE_REGEX
diff --git a/utils/file.c b/utils/file.c
index c460e49..75a8a1c 100644
--- a/utils/file.c
+++ b/utils/file.c
@@ -26,6 +26,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <fcntl.h>
#include <errno.h>
#include "desktop/gui_internal.h"
@@ -318,16 +319,13 @@ nserror netsurf_mkdir_all(const char *fname)
nserror
netsurf_recursive_rm(const char *path)
{
- struct dirent **listing = NULL; /* directory entry listing */
- int nentries, ent;
+ DIR *parent;
+ struct dirent *entry;
nserror ret = NSERROR_OK;
struct stat ent_stat; /* stat result of leaf entry */
- char *leafpath = NULL;
- const char *leafname;
-
- nentries = scandir(path, &listing, 0, alphasort);
- if (nentries < 0) {
+ parent = opendir(path);
+ if (parent == NULL) {
switch (errno) {
case ENOENT:
return NSERROR_NOT_FOUND;
@@ -336,26 +334,44 @@ netsurf_recursive_rm(const char *path)
}
}
- for (ent = 0; ent < nentries; ent++) {
- leafname = listing[ent]->d_name;
- if (strcmp(leafname, ".") == 0 ||
- strcmp(leafname, "..") == 0)
+ while ((entry = readdir(parent))) {
+ char *leafpath = NULL;
+
+ if (strcmp(entry->d_name, ".") == 0 ||
+ strcmp(entry->d_name, "..") == 0)
continue;
- ret = netsurf_mkpath(&leafpath, NULL, 2, path, leafname);
- if (ret != NSERROR_OK) goto out;
+
+ ret = netsurf_mkpath(&leafpath, NULL, 2, path, entry->d_name);
+ if (ret != NSERROR_OK)
+ goto out;
+
+#if (defined(HAVE_DIRFD) && defined(HAVE_FSTATAT))
+ if (fstatat(dirfd(parent), entry->d_name, &ent_stat,
+ AT_SYMLINK_NOFOLLOW) != 0) {
+#else
if (stat(leafpath, &ent_stat) != 0) {
+#endif
+ free(leafpath);
goto out_via_errno;
}
if (S_ISDIR(ent_stat.st_mode)) {
ret = netsurf_recursive_rm(leafpath);
- if (ret != NSERROR_OK) goto out;
+ if (ret != NSERROR_OK) {
+ free(leafpath);
+ goto out;
+ }
} else {
+#if (defined(HAVE_DIRFD) && defined(HAVE_UNLINKAT))
+ if (unlinkat(dirfd(parent), entry->d_name, 0) != 0) {
+#else
if (unlink(leafpath) != 0) {
+#endif
+ free(leafpath);
goto out_via_errno;
}
}
+
free(leafpath);
- leafpath = NULL;
}
if (rmdir(path) != 0) {
@@ -373,16 +389,7 @@ out_via_errno:
ret = NSERROR_UNKNOWN;
}
out:
- if (listing != NULL) {
- for (ent = 0; ent < nentries; ent++) {
- free(listing[ent]);
- }
- free(listing);
- }
-
- if (leafpath != NULL) {
- free(leafpath);
- }
+ closedir(parent);
return ret;
}
diff --git a/utils/filename.c b/utils/filename.c
index 00ade74..346fa85 100644
--- a/utils/filename.c
+++ b/utils/filename.c
@@ -29,10 +29,13 @@
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
+#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include "utils/dirent.h"
+#include "utils/errors.h"
+#include "utils/file.h"
#include "utils/filename.h"
#include "utils/log.h"
#include "utils/utils.h"
@@ -55,7 +58,6 @@ static char filename_directory[256];
static struct directory *filename_create_directory(const char *prefix);
static bool filename_flush_directory(const char *folder, int depth);
-static bool filename_delete_recursive(char *folder);
/**
* Request a new, unique, filename.
@@ -272,6 +274,8 @@ bool filename_flush_directory(const char *folder, int depth)
}
parent = opendir(folder);
+ if (parent == NULL)
+ return false;
while ((entry = readdir(parent))) {
int written;
@@ -288,7 +292,12 @@ bool filename_flush_directory(const char *folder, int depth)
child[sizeof(child) - 1] = '\0';
}
+#if (defined(HAVE_DIRFD) && defined(HAVE_FSTATAT))
+ if (fstatat(dirfd(parent), entry->d_name, &statbuf,
+ AT_SYMLINK_NOFOLLOW) == -1) {
+#else
if (stat(child, &statbuf) == -1) {
+#endif
NSLOG(netsurf, INFO, "Unable to stat %s: %s", child,
strerror(errno));
continue;
@@ -354,14 +363,20 @@ bool filename_flush_directory(const char *folder, int depth)
/* delete or recurse */
if (del) {
- if (S_ISDIR(statbuf.st_mode))
- filename_delete_recursive(child);
-
- if (remove(child))
- NSLOG(netsurf, INFO, "Failed to remove '%s'",
- child);
- else
- changed = true;
+ if (S_ISDIR(statbuf.st_mode)) {
+ changed = (netsurf_recursive_rm(child) ==
+ NSERROR_OK);
+ } else {
+#if (defined(HAVE_DIRFD) && defined(HAVE_UNLINKAT))
+ if (unlinkat(dirfd(parent), entry->d_name, 0)) {
+#else
+ if (unlink(child)) {
+#endif
+ NSLOG(netsurf, INFO,
+ "Failed to remove '%s'", child);
+ } else
+ changed = true;
+ }
} else {
while (filename_flush_directory(child, depth + 1));
}
@@ -374,61 +389,6 @@ bool filename_flush_directory(const char *folder, int depth)
/**
- * Recursively deletes the contents of a directory
- *
- * \param folder the directory to delete
- * \return true on success, false otherwise
- */
-bool filename_delete_recursive(char *folder)
-{
- DIR *parent;
- struct dirent *entry;
- char child[256];
- struct stat statbuf;
-
- parent = opendir(folder);
-
- while ((entry = readdir(parent))) {
- int written;
-
- /* Ignore '.' and '..' */
- if (strcmp(entry->d_name, ".") == 0 ||
- strcmp(entry->d_name, "..") == 0)
- continue;
-
- written = snprintf(child, sizeof(child), "%s/%s",
- folder, entry->d_name);
- if (written == sizeof(child)) {
- child[sizeof(child) - 1] = '\0';
- }
-
- if (stat(child, &statbuf) == -1) {
- NSLOG(netsurf, INFO, "Unable to stat %s: %s", child,
- strerror(errno));
- continue;
- }
-
- if (S_ISDIR(statbuf.st_mode)) {
- if (!filename_delete_recursive(child)) {
- closedir(parent);
- return false;
- }
- }
-
- if (remove(child)) {
- NSLOG(netsurf, INFO, "Failed to remove '%s'", child);
- closedir(parent);
- return false;
- }
- }
-
- closedir(parent);
-
- return true;
-}
-
-
-/**
* Creates a new directory.
*
* \param prefix the prefix to use, or NULL to allocate a new one
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=41f0a5a36ecc6381880...
commit 41f0a5a36ecc6381880bd19b4f6838ac22f7d833
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Buildsystem: fix RISC OS AOF matching
diff --git a/Makefile b/Makefile
index f66f796..828f83b 100644
--- a/Makefile
+++ b/Makefile
@@ -333,7 +333,7 @@ ifneq ($(TARGET),riscos)
$(Q)$(CC) -o $(EXETARGET) $(OBJECTS) $(LDFLAGS) > $(DEPROOT)/link-raw.d
else
@# RISC OS targets are a bit special: we need to convert ELF -> AIF
- ifeq ($(SUBTARGET),riscos-aof)
+ ifeq ($(SUBTARGET),-aof)
$(Q)$(CC) -o $(EXETARGET) $(OBJECTS) $(LDFLAGS) > $(DEPROOT)/link-raw.d
else
$(Q)$(CXX) -o $(EXETARGET:,ff8=,e1f) $(OBJECTS) $(LDFLAGS) > $(DEPROOT)/link-raw.d
-----------------------------------------------------------------------
Summary of changes:
Makefile | 2 +-
utils/config.h | 9 ++++++
utils/file.c | 57 +++++++++++++++++++----------------
utils/filename.c | 88 +++++++++++++++---------------------------------------
4 files changed, 66 insertions(+), 90 deletions(-)
diff --git a/Makefile b/Makefile
index f66f796..828f83b 100644
--- a/Makefile
+++ b/Makefile
@@ -333,7 +333,7 @@ ifneq ($(TARGET),riscos)
$(Q)$(CC) -o $(EXETARGET) $(OBJECTS) $(LDFLAGS) > $(DEPROOT)/link-raw.d
else
@# RISC OS targets are a bit special: we need to convert ELF -> AIF
- ifeq ($(SUBTARGET),riscos-aof)
+ ifeq ($(SUBTARGET),-aof)
$(Q)$(CC) -o $(EXETARGET) $(OBJECTS) $(LDFLAGS) > $(DEPROOT)/link-raw.d
else
$(Q)$(CXX) -o $(EXETARGET:,ff8=,e1f) $(OBJECTS) $(LDFLAGS) > $(DEPROOT)/link-raw.d
diff --git a/utils/config.h b/utils/config.h
index 0227f41..f54326d 100644
--- a/utils/config.h
+++ b/utils/config.h
@@ -146,6 +146,15 @@ char *realpath(const char *path, char *resolved_path);
#undef HAVE_SCANDIR
#endif
+#define HAVE_DIRFD
+#define HAVE_UNLINKAT
+#define HAVE_FSTATAT
+#if (defined(_WIN32) || defined(__riscos__) || defined(__HAIKU__) || defined(__BEOS__) || defined(__amigaos4__) || defined(__AMIGA__) || defined(__MINT__))
+#undef HAVE_DIRFD
+#undef HAVE_UNLINKAT
+#undef HAVE_FSTATAT
+#endif
+
#define HAVE_REGEX
#if (defined(__serenity__))
#undef HAVE_REGEX
diff --git a/utils/file.c b/utils/file.c
index c460e49..75a8a1c 100644
--- a/utils/file.c
+++ b/utils/file.c
@@ -26,6 +26,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <fcntl.h>
#include <errno.h>
#include "desktop/gui_internal.h"
@@ -318,16 +319,13 @@ nserror netsurf_mkdir_all(const char *fname)
nserror
netsurf_recursive_rm(const char *path)
{
- struct dirent **listing = NULL; /* directory entry listing */
- int nentries, ent;
+ DIR *parent;
+ struct dirent *entry;
nserror ret = NSERROR_OK;
struct stat ent_stat; /* stat result of leaf entry */
- char *leafpath = NULL;
- const char *leafname;
-
- nentries = scandir(path, &listing, 0, alphasort);
- if (nentries < 0) {
+ parent = opendir(path);
+ if (parent == NULL) {
switch (errno) {
case ENOENT:
return NSERROR_NOT_FOUND;
@@ -336,26 +334,44 @@ netsurf_recursive_rm(const char *path)
}
}
- for (ent = 0; ent < nentries; ent++) {
- leafname = listing[ent]->d_name;
- if (strcmp(leafname, ".") == 0 ||
- strcmp(leafname, "..") == 0)
+ while ((entry = readdir(parent))) {
+ char *leafpath = NULL;
+
+ if (strcmp(entry->d_name, ".") == 0 ||
+ strcmp(entry->d_name, "..") == 0)
continue;
- ret = netsurf_mkpath(&leafpath, NULL, 2, path, leafname);
- if (ret != NSERROR_OK) goto out;
+
+ ret = netsurf_mkpath(&leafpath, NULL, 2, path, entry->d_name);
+ if (ret != NSERROR_OK)
+ goto out;
+
+#if (defined(HAVE_DIRFD) && defined(HAVE_FSTATAT))
+ if (fstatat(dirfd(parent), entry->d_name, &ent_stat,
+ AT_SYMLINK_NOFOLLOW) != 0) {
+#else
if (stat(leafpath, &ent_stat) != 0) {
+#endif
+ free(leafpath);
goto out_via_errno;
}
if (S_ISDIR(ent_stat.st_mode)) {
ret = netsurf_recursive_rm(leafpath);
- if (ret != NSERROR_OK) goto out;
+ if (ret != NSERROR_OK) {
+ free(leafpath);
+ goto out;
+ }
} else {
+#if (defined(HAVE_DIRFD) && defined(HAVE_UNLINKAT))
+ if (unlinkat(dirfd(parent), entry->d_name, 0) != 0) {
+#else
if (unlink(leafpath) != 0) {
+#endif
+ free(leafpath);
goto out_via_errno;
}
}
+
free(leafpath);
- leafpath = NULL;
}
if (rmdir(path) != 0) {
@@ -373,16 +389,7 @@ out_via_errno:
ret = NSERROR_UNKNOWN;
}
out:
- if (listing != NULL) {
- for (ent = 0; ent < nentries; ent++) {
- free(listing[ent]);
- }
- free(listing);
- }
-
- if (leafpath != NULL) {
- free(leafpath);
- }
+ closedir(parent);
return ret;
}
diff --git a/utils/filename.c b/utils/filename.c
index 00ade74..346fa85 100644
--- a/utils/filename.c
+++ b/utils/filename.c
@@ -29,10 +29,13 @@
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
+#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include "utils/dirent.h"
+#include "utils/errors.h"
+#include "utils/file.h"
#include "utils/filename.h"
#include "utils/log.h"
#include "utils/utils.h"
@@ -55,7 +58,6 @@ static char filename_directory[256];
static struct directory *filename_create_directory(const char *prefix);
static bool filename_flush_directory(const char *folder, int depth);
-static bool filename_delete_recursive(char *folder);
/**
* Request a new, unique, filename.
@@ -272,6 +274,8 @@ bool filename_flush_directory(const char *folder, int depth)
}
parent = opendir(folder);
+ if (parent == NULL)
+ return false;
while ((entry = readdir(parent))) {
int written;
@@ -288,7 +292,12 @@ bool filename_flush_directory(const char *folder, int depth)
child[sizeof(child) - 1] = '\0';
}
+#if (defined(HAVE_DIRFD) && defined(HAVE_FSTATAT))
+ if (fstatat(dirfd(parent), entry->d_name, &statbuf,
+ AT_SYMLINK_NOFOLLOW) == -1) {
+#else
if (stat(child, &statbuf) == -1) {
+#endif
NSLOG(netsurf, INFO, "Unable to stat %s: %s", child,
strerror(errno));
continue;
@@ -354,14 +363,20 @@ bool filename_flush_directory(const char *folder, int depth)
/* delete or recurse */
if (del) {
- if (S_ISDIR(statbuf.st_mode))
- filename_delete_recursive(child);
-
- if (remove(child))
- NSLOG(netsurf, INFO, "Failed to remove '%s'",
- child);
- else
- changed = true;
+ if (S_ISDIR(statbuf.st_mode)) {
+ changed = (netsurf_recursive_rm(child) ==
+ NSERROR_OK);
+ } else {
+#if (defined(HAVE_DIRFD) && defined(HAVE_UNLINKAT))
+ if (unlinkat(dirfd(parent), entry->d_name, 0)) {
+#else
+ if (unlink(child)) {
+#endif
+ NSLOG(netsurf, INFO,
+ "Failed to remove '%s'", child);
+ } else
+ changed = true;
+ }
} else {
while (filename_flush_directory(child, depth + 1));
}
@@ -374,61 +389,6 @@ bool filename_flush_directory(const char *folder, int depth)
/**
- * Recursively deletes the contents of a directory
- *
- * \param folder the directory to delete
- * \return true on success, false otherwise
- */
-bool filename_delete_recursive(char *folder)
-{
- DIR *parent;
- struct dirent *entry;
- char child[256];
- struct stat statbuf;
-
- parent = opendir(folder);
-
- while ((entry = readdir(parent))) {
- int written;
-
- /* Ignore '.' and '..' */
- if (strcmp(entry->d_name, ".") == 0 ||
- strcmp(entry->d_name, "..") == 0)
- continue;
-
- written = snprintf(child, sizeof(child), "%s/%s",
- folder, entry->d_name);
- if (written == sizeof(child)) {
- child[sizeof(child) - 1] = '\0';
- }
-
- if (stat(child, &statbuf) == -1) {
- NSLOG(netsurf, INFO, "Unable to stat %s: %s", child,
- strerror(errno));
- continue;
- }
-
- if (S_ISDIR(statbuf.st_mode)) {
- if (!filename_delete_recursive(child)) {
- closedir(parent);
- return false;
- }
- }
-
- if (remove(child)) {
- NSLOG(netsurf, INFO, "Failed to remove '%s'", child);
- closedir(parent);
- return false;
- }
- }
-
- closedir(parent);
-
- return true;
-}
-
-
-/**
* Creates a new directory.
*
* \param prefix the prefix to use, or NULL to allocate a new one
--
NetSurf Browser
4 months, 3 weeks
netsurf: branch master updated. release/3.10-301-g1810fbf
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/1810fbfe22a1202ddbd80...
...commit http://git.netsurf-browser.org/netsurf.git/commit/1810fbfe22a1202ddbd8024...
...tree http://git.netsurf-browser.org/netsurf.git/tree/1810fbfe22a1202ddbd8024dd...
The branch, master has been updated
via 1810fbfe22a1202ddbd8024dde4ec10882cc3e76 (commit)
from 991f657ecdcb26cd7e40ab44463f189b1e89b014 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=1810fbfe22a1202ddbd...
commit 1810fbfe22a1202ddbd8024dde4ec10882cc3e76
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Revert "utils: file: Use fstatat and unlinkat"
On may of the platforms we build for (RISC OS, Windows, Amiga OS4,
Amiga OS3, and Atari), this was causing:
- utils/file.c:329 error: 'O_DIRECTORY' undeclared
- utils/file.c:357 error: 'AT_SYMLINK_NOFOLLOW' undeclared
This reverts commit ef00567b029ec007ceab342a2ed1addaa5f63be6.
diff --git a/utils/file.c b/utils/file.c
index 3cf12d5..c460e49 100644
--- a/utils/file.c
+++ b/utils/file.c
@@ -26,7 +26,6 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
-#include <fcntl.h>
#include <errno.h>
#include "desktop/gui_internal.h"
@@ -323,23 +322,12 @@ netsurf_recursive_rm(const char *path)
int nentries, ent;
nserror ret = NSERROR_OK;
struct stat ent_stat; /* stat result of leaf entry */
+ char *leafpath = NULL;
const char *leafname;
- int dirfd;
-
- dirfd = open(path, O_DIRECTORY);
- if (dirfd == -1) {
- switch (errno) {
- case ENOENT:
- return NSERROR_NOT_FOUND;
- default:
- return NSERROR_UNKNOWN;
- }
- }
nentries = scandir(path, &listing, 0, alphasort);
- if (nentries < 0) {
- close(dirfd);
+ if (nentries < 0) {
switch (errno) {
case ENOENT:
return NSERROR_NOT_FOUND;
@@ -353,26 +341,21 @@ netsurf_recursive_rm(const char *path)
if (strcmp(leafname, ".") == 0 ||
strcmp(leafname, "..") == 0)
continue;
- if (fstatat(dirfd, leafname, &ent_stat,
- AT_SYMLINK_NOFOLLOW) != 0) {
+ ret = netsurf_mkpath(&leafpath, NULL, 2, path, leafname);
+ if (ret != NSERROR_OK) goto out;
+ if (stat(leafpath, &ent_stat) != 0) {
goto out_via_errno;
}
if (S_ISDIR(ent_stat.st_mode)) {
- char *leafpath = NULL;
-
- ret = netsurf_mkpath(&leafpath, NULL, 2, path, leafname);
- if (ret != NSERROR_OK)
- goto out;
-
ret = netsurf_recursive_rm(leafpath);
- free(leafpath);
- if (ret != NSERROR_OK)
- goto out;
+ if (ret != NSERROR_OK) goto out;
} else {
- if (unlinkat(dirfd, leafname, 0) != 0) {
+ if (unlink(leafpath) != 0) {
goto out_via_errno;
}
}
+ free(leafpath);
+ leafpath = NULL;
}
if (rmdir(path) != 0) {
@@ -397,7 +380,9 @@ out:
free(listing);
}
- close(dirfd);
+ if (leafpath != NULL) {
+ free(leafpath);
+ }
return ret;
}
-----------------------------------------------------------------------
Summary of changes:
utils/file.c | 39 ++++++++++++---------------------------
1 file changed, 12 insertions(+), 27 deletions(-)
diff --git a/utils/file.c b/utils/file.c
index 3cf12d5..c460e49 100644
--- a/utils/file.c
+++ b/utils/file.c
@@ -26,7 +26,6 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
-#include <fcntl.h>
#include <errno.h>
#include "desktop/gui_internal.h"
@@ -323,23 +322,12 @@ netsurf_recursive_rm(const char *path)
int nentries, ent;
nserror ret = NSERROR_OK;
struct stat ent_stat; /* stat result of leaf entry */
+ char *leafpath = NULL;
const char *leafname;
- int dirfd;
-
- dirfd = open(path, O_DIRECTORY);
- if (dirfd == -1) {
- switch (errno) {
- case ENOENT:
- return NSERROR_NOT_FOUND;
- default:
- return NSERROR_UNKNOWN;
- }
- }
nentries = scandir(path, &listing, 0, alphasort);
- if (nentries < 0) {
- close(dirfd);
+ if (nentries < 0) {
switch (errno) {
case ENOENT:
return NSERROR_NOT_FOUND;
@@ -353,26 +341,21 @@ netsurf_recursive_rm(const char *path)
if (strcmp(leafname, ".") == 0 ||
strcmp(leafname, "..") == 0)
continue;
- if (fstatat(dirfd, leafname, &ent_stat,
- AT_SYMLINK_NOFOLLOW) != 0) {
+ ret = netsurf_mkpath(&leafpath, NULL, 2, path, leafname);
+ if (ret != NSERROR_OK) goto out;
+ if (stat(leafpath, &ent_stat) != 0) {
goto out_via_errno;
}
if (S_ISDIR(ent_stat.st_mode)) {
- char *leafpath = NULL;
-
- ret = netsurf_mkpath(&leafpath, NULL, 2, path, leafname);
- if (ret != NSERROR_OK)
- goto out;
-
ret = netsurf_recursive_rm(leafpath);
- free(leafpath);
- if (ret != NSERROR_OK)
- goto out;
+ if (ret != NSERROR_OK) goto out;
} else {
- if (unlinkat(dirfd, leafname, 0) != 0) {
+ if (unlink(leafpath) != 0) {
goto out_via_errno;
}
}
+ free(leafpath);
+ leafpath = NULL;
}
if (rmdir(path) != 0) {
@@ -397,7 +380,9 @@ out:
free(listing);
}
- close(dirfd);
+ if (leafpath != NULL) {
+ free(leafpath);
+ }
return ret;
}
--
NetSurf Browser
4 months, 3 weeks
toolchains: branch master updated. ab619018e422ed8b46d452793b3c72b062b84d0a
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/toolchains.git/shortlog/ab619018e422ed8b46...
...commit http://git.netsurf-browser.org/toolchains.git/commit/ab619018e422ed8b46d4...
...tree http://git.netsurf-browser.org/toolchains.git/tree/ab619018e422ed8b46d452...
The branch, master has been updated
via ab619018e422ed8b46d452793b3c72b062b84d0a (commit)
from 2bbddd7aaabeae11c1862787ef6f99b3b816324a (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=ab619018e422ed8b...
commit ab619018e422ed8b46d452793b3c72b062b84d0a
Author: Michael Drake <michael.drake(a)codethink.co.uk>
Commit: Michael Drake <michael.drake(a)codethink.co.uk>
sdk: libcurl: Significantly faster https connections
Making HTTPS connections was slow because libcurl forces openssl
to rebuild the same X509_STORE from the same cabundle every time
a connection is made. This is a slow process and it can happen
many times per page.
These patches change libcurl to keep the built X509_STORE cached
and reuse it for subsequent connections.
These patches are being upstreamed here:
https://github.com/curl/curl/pull/9620
diff --git a/sdk/recipes/patches/libcurl/0002-openssl-split-out-x509-store-loading.p b/sdk/recipes/patches/libcurl/0002-openssl-split-out-x509-store-loading.p
new file mode 100644
index 0000000..658c801
--- /dev/null
+++ b/sdk/recipes/patches/libcurl/0002-openssl-split-out-x509-store-loading.p
@@ -0,0 +1,554 @@
+diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
+index ad2efa558..981075838 100644
+--- lib/vtls/openssl.c
++++ lib/vtls/openssl.c
+@@ -2891,13 +2891,274 @@ static CURLcode load_cacert_from_memory(SSL_CTX *ctx,
+ return (count > 0 ? CURLE_OK : CURLE_SSL_CACERT_BADFILE);
+ }
+
++static CURLcode populate_x509_store(struct Curl_easy *data,
++ struct connectdata *conn, int sockindex)
++{
++ CURLcode result = CURLE_OK;
++ X509_LOOKUP *lookup = NULL;
++ const struct curl_blob *ca_info_blob = SSL_CONN_CONFIG(ca_info_blob);
++ const char * const ssl_cafile =
++ /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
++ (ca_info_blob ? NULL : SSL_CONN_CONFIG(CAfile));
++ const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
++ const char * const ssl_crlfile = SSL_SET_OPTION(primary.CRLfile);
++ const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
++ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
++ struct ssl_backend_data *backend = connssl->backend;
++ bool imported_native_ca = false;
++
++#if defined(USE_WIN32_CRYPTO)
++ /* Import certificates from the Windows root certificate store if requested.
++ https://stackoverflow.com/questions/9507184/
++ https://github.com/d3x0r/SACK/blob/master/src/netlib/ssl_layer.c#L1037
++ https://datatracker.ietf.org/doc/html/rfc5280 */
++ if((SSL_CONN_CONFIG(verifypeer) || SSL_CONN_CONFIG(verifyhost)) &&
++ (SSL_SET_OPTION(native_ca_store))) {
++ X509_STORE *store = SSL_CTX_get_cert_store(backend->ctx);
++ HCERTSTORE hStore = CertOpenSystemStore(0, TEXT("ROOT"));
++
++ if(hStore) {
++ PCCERT_CONTEXT pContext = NULL;
++ /* The array of enhanced key usage OIDs will vary per certificate and is
++ declared outside of the loop so that rather than malloc/free each
++ iteration we can grow it with realloc, when necessary. */
++ CERT_ENHKEY_USAGE *enhkey_usage = NULL;
++ DWORD enhkey_usage_size = 0;
++
++ /* This loop makes a best effort to import all valid certificates from
++ the MS root store. If a certificate cannot be imported it is skipped.
++ 'result' is used to store only hard-fail conditions (such as out of
++ memory) that cause an early break. */
++ result = CURLE_OK;
++ for(;;) {
++ X509 *x509;
++ FILETIME now;
++ BYTE key_usage[2];
++ DWORD req_size;
++ const unsigned char *encoded_cert;
++#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
++ char cert_name[256];
++#endif
++
++ pContext = CertEnumCertificatesInStore(hStore, pContext);
++ if(!pContext)
++ break;
++
++#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
++ if(!CertGetNameStringA(pContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
++ NULL, cert_name, sizeof(cert_name))) {
++ strcpy(cert_name, "Unknown");
++ }
++ infof(data, "SSL: Checking cert \"%s\"", cert_name);
++#endif
++
++ encoded_cert = (const unsigned char *)pContext->pbCertEncoded;
++ if(!encoded_cert)
++ continue;
++
++ GetSystemTimeAsFileTime(&now);
++ if(CompareFileTime(&pContext->pCertInfo->NotBefore, &now) > 0 ||
++ CompareFileTime(&now, &pContext->pCertInfo->NotAfter) > 0)
++ continue;
++
++ /* If key usage exists check for signing attribute */
++ if(CertGetIntendedKeyUsage(pContext->dwCertEncodingType,
++ pContext->pCertInfo,
++ key_usage, sizeof(key_usage))) {
++ if(!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE))
++ continue;
++ }
++ else if(GetLastError())
++ continue;
++
++ /* If enhanced key usage exists check for server auth attribute.
++ *
++ * Note "In a Microsoft environment, a certificate might also have EKU
++ * extended properties that specify valid uses for the certificate."
++ * The call below checks both, and behavior varies depending on what is
++ * found. For more details see CertGetEnhancedKeyUsage doc.
++ */
++ if(CertGetEnhancedKeyUsage(pContext, 0, NULL, &req_size)) {
++ if(req_size && req_size > enhkey_usage_size) {
++ void *tmp = realloc(enhkey_usage, req_size);
++
++ if(!tmp) {
++ failf(data, "SSL: Out of memory allocating for OID list");
++ result = CURLE_OUT_OF_MEMORY;
++ break;
++ }
++
++ enhkey_usage = (CERT_ENHKEY_USAGE *)tmp;
++ enhkey_usage_size = req_size;
++ }
++
++ if(CertGetEnhancedKeyUsage(pContext, 0, enhkey_usage, &req_size)) {
++ if(!enhkey_usage->cUsageIdentifier) {
++ /* "If GetLastError returns CRYPT_E_NOT_FOUND, the certificate is
++ good for all uses. If it returns zero, the certificate has no
++ valid uses." */
++ if((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND)
++ continue;
++ }
++ else {
++ DWORD i;
++ bool found = false;
++
++ for(i = 0; i < enhkey_usage->cUsageIdentifier; ++i) {
++ if(!strcmp("1.3.6.1.5.5.7.3.1" /* OID server auth */,
++ enhkey_usage->rgpszUsageIdentifier[i])) {
++ found = true;
++ break;
++ }
++ }
++
++ if(!found)
++ continue;
++ }
++ }
++ else
++ continue;
++ }
++ else
++ continue;
++
++ x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded);
++ if(!x509)
++ continue;
++
++ /* Try to import the certificate. This may fail for legitimate reasons
++ such as duplicate certificate, which is allowed by MS but not
++ OpenSSL. */
++ if(X509_STORE_add_cert(store, x509) == 1) {
++#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
++ infof(data, "SSL: Imported cert \"%s\"", cert_name);
++#endif
++ imported_native_ca = true;
++ }
++ X509_free(x509);
++ }
++
++ free(enhkey_usage);
++ CertFreeCertificateContext(pContext);
++ CertCloseStore(hStore, 0);
++
++ if(result)
++ return result;
++ }
++ if(imported_native_ca)
++ infof(data, "successfully imported Windows CA store");
++ else
++ infof(data, "error importing Windows CA store, continuing anyway");
++ }
++#endif
++
++ if(ca_info_blob) {
++ result = load_cacert_from_memory(backend->ctx, ca_info_blob);
++ if(result) {
++ if(result == CURLE_OUT_OF_MEMORY ||
++ (verifypeer && !imported_native_ca)) {
++ failf(data, "error importing CA certificate blob");
++ return result;
++ }
++ /* Only warn if no certificate verification is required. */
++ infof(data, "error importing CA certificate blob, continuing anyway");
++ }
++ }
++
++ if(verifypeer && !imported_native_ca && (ssl_cafile || ssl_capath)) {
++#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
++ /* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */
++ if(ssl_cafile &&
++ !SSL_CTX_load_verify_file(backend->ctx, ssl_cafile)) {
++ /* Fail if we insist on successfully verifying the server. */
++ failf(data, "error setting certificate file: %s", ssl_cafile);
++ return CURLE_SSL_CACERT_BADFILE;
++ }
++ if(ssl_capath &&
++ !SSL_CTX_load_verify_dir(backend->ctx, ssl_capath)) {
++ /* Fail if we insist on successfully verifying the server. */
++ failf(data, "error setting certificate path: %s", ssl_capath);
++ return CURLE_SSL_CACERT_BADFILE;
++ }
++#else
++ /* tell OpenSSL where to find CA certificates that are used to verify the
++ server's certificate. */
++ if(!SSL_CTX_load_verify_locations(backend->ctx, ssl_cafile, ssl_capath)) {
++ /* Fail if we insist on successfully verifying the server. */
++ failf(data, "error setting certificate verify locations:"
++ " CAfile: %s CApath: %s",
++ ssl_cafile ? ssl_cafile : "none",
++ ssl_capath ? ssl_capath : "none");
++ return CURLE_SSL_CACERT_BADFILE;
++ }
++#endif
++ infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
++ infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
++ }
++
++#ifdef CURL_CA_FALLBACK
++ if(verifypeer &&
++ !ca_info_blob && !ssl_cafile && !ssl_capath && !imported_native_ca) {
++ /* verifying the peer without any CA certificates won't
++ work so use openssl's built-in default as fallback */
++ SSL_CTX_set_default_verify_paths(backend->ctx);
++ }
++#endif
++
++ if(ssl_crlfile) {
++ /* tell OpenSSL where to find CRL file that is used to check certificate
++ * revocation */
++ lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(backend->ctx),
++ X509_LOOKUP_file());
++ if(!lookup ||
++ (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) {
++ failf(data, "error loading CRL file: %s", ssl_crlfile);
++ return CURLE_SSL_CRL_BADFILE;
++ }
++ /* Everything is fine. */
++ infof(data, "successfully loaded CRL file:");
++ X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
++ X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
++
++ infof(data, " CRLfile: %s", ssl_crlfile);
++ }
++
++ if(verifypeer) {
++ /* Try building a chain using issuers in the trusted store first to avoid
++ problems with server-sent legacy intermediates. Newer versions of
++ OpenSSL do alternate chain checking by default but we do not know how to
++ determine that in a reliable manner.
++ https://rt.openssl.org/Ticket/Display.html?id=3621&user=guest&pass=guest
++ */
++#if defined(X509_V_FLAG_TRUSTED_FIRST)
++ X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
++ X509_V_FLAG_TRUSTED_FIRST);
++#endif
++#ifdef X509_V_FLAG_PARTIAL_CHAIN
++ if(!SSL_SET_OPTION(no_partialchain) && !ssl_crlfile) {
++ /* Have intermediate certificates in the trust store be treated as
++ trust-anchors, in the same way as self-signed root CA certificates
++ are. This allows users to verify servers using the intermediate cert
++ only, instead of needing the whole chain.
++
++ Due to OpenSSL bug https://github.com/openssl/openssl/issues/5081 we
++ cannot do partial chains with a CRL check.
++ */
++ X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
++ X509_V_FLAG_PARTIAL_CHAIN);
++ }
++#endif
++ }
++
++ return result;
++}
++
+ static CURLcode ossl_connect_step1(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
+ {
+ CURLcode result = CURLE_OK;
+ char *ciphers;
+ SSL_METHOD_QUAL SSL_METHOD *req_method = NULL;
+- X509_LOOKUP *lookup = NULL;
+ curl_socket_t sockfd = conn->sock[sockindex];
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ ctx_option_t ctx_options = 0;
+@@ -2919,17 +3180,10 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
+ #endif
+ char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);
+ const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob);
+- const struct curl_blob *ca_info_blob = SSL_CONN_CONFIG(ca_info_blob);
+ const char * const ssl_cert_type = SSL_SET_OPTION(cert_type);
+- const char * const ssl_cafile =
+- /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
+- (ca_info_blob ? NULL : SSL_CONN_CONFIG(CAfile));
+- const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
+ const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
+- const char * const ssl_crlfile = SSL_SET_OPTION(primary.CRLfile);
+ char error_buffer[256];
+ struct ssl_backend_data *backend = connssl->backend;
+- bool imported_native_ca = false;
+
+ DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
+ DEBUGASSERT(backend);
+@@ -3196,249 +3450,9 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
+ }
+ #endif
+
+-
+-#if defined(USE_WIN32_CRYPTO)
+- /* Import certificates from the Windows root certificate store if requested.
+- https://stackoverflow.com/questions/9507184/
+- https://github.com/d3x0r/SACK/blob/master/src/netlib/ssl_layer.c#L1037
+- https://datatracker.ietf.org/doc/html/rfc5280 */
+- if((SSL_CONN_CONFIG(verifypeer) || SSL_CONN_CONFIG(verifyhost)) &&
+- (SSL_SET_OPTION(native_ca_store))) {
+- X509_STORE *store = SSL_CTX_get_cert_store(backend->ctx);
+- HCERTSTORE hStore = CertOpenSystemStore(0, TEXT("ROOT"));
+-
+- if(hStore) {
+- PCCERT_CONTEXT pContext = NULL;
+- /* The array of enhanced key usage OIDs will vary per certificate and is
+- declared outside of the loop so that rather than malloc/free each
+- iteration we can grow it with realloc, when necessary. */
+- CERT_ENHKEY_USAGE *enhkey_usage = NULL;
+- DWORD enhkey_usage_size = 0;
+-
+- /* This loop makes a best effort to import all valid certificates from
+- the MS root store. If a certificate cannot be imported it is skipped.
+- 'result' is used to store only hard-fail conditions (such as out of
+- memory) that cause an early break. */
+- result = CURLE_OK;
+- for(;;) {
+- X509 *x509;
+- FILETIME now;
+- BYTE key_usage[2];
+- DWORD req_size;
+- const unsigned char *encoded_cert;
+-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+- char cert_name[256];
+-#endif
+-
+- pContext = CertEnumCertificatesInStore(hStore, pContext);
+- if(!pContext)
+- break;
+-
+-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+- if(!CertGetNameStringA(pContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
+- NULL, cert_name, sizeof(cert_name))) {
+- strcpy(cert_name, "Unknown");
+- }
+- infof(data, "SSL: Checking cert \"%s\"", cert_name);
+-#endif
+-
+- encoded_cert = (const unsigned char *)pContext->pbCertEncoded;
+- if(!encoded_cert)
+- continue;
+-
+- GetSystemTimeAsFileTime(&now);
+- if(CompareFileTime(&pContext->pCertInfo->NotBefore, &now) > 0 ||
+- CompareFileTime(&now, &pContext->pCertInfo->NotAfter) > 0)
+- continue;
+-
+- /* If key usage exists check for signing attribute */
+- if(CertGetIntendedKeyUsage(pContext->dwCertEncodingType,
+- pContext->pCertInfo,
+- key_usage, sizeof(key_usage))) {
+- if(!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE))
+- continue;
+- }
+- else if(GetLastError())
+- continue;
+-
+- /* If enhanced key usage exists check for server auth attribute.
+- *
+- * Note "In a Microsoft environment, a certificate might also have EKU
+- * extended properties that specify valid uses for the certificate."
+- * The call below checks both, and behavior varies depending on what is
+- * found. For more details see CertGetEnhancedKeyUsage doc.
+- */
+- if(CertGetEnhancedKeyUsage(pContext, 0, NULL, &req_size)) {
+- if(req_size && req_size > enhkey_usage_size) {
+- void *tmp = realloc(enhkey_usage, req_size);
+-
+- if(!tmp) {
+- failf(data, "SSL: Out of memory allocating for OID list");
+- result = CURLE_OUT_OF_MEMORY;
+- break;
+- }
+-
+- enhkey_usage = (CERT_ENHKEY_USAGE *)tmp;
+- enhkey_usage_size = req_size;
+- }
+-
+- if(CertGetEnhancedKeyUsage(pContext, 0, enhkey_usage, &req_size)) {
+- if(!enhkey_usage->cUsageIdentifier) {
+- /* "If GetLastError returns CRYPT_E_NOT_FOUND, the certificate is
+- good for all uses. If it returns zero, the certificate has no
+- valid uses." */
+- if((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND)
+- continue;
+- }
+- else {
+- DWORD i;
+- bool found = false;
+-
+- for(i = 0; i < enhkey_usage->cUsageIdentifier; ++i) {
+- if(!strcmp("1.3.6.1.5.5.7.3.1" /* OID server auth */,
+- enhkey_usage->rgpszUsageIdentifier[i])) {
+- found = true;
+- break;
+- }
+- }
+-
+- if(!found)
+- continue;
+- }
+- }
+- else
+- continue;
+- }
+- else
+- continue;
+-
+- x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded);
+- if(!x509)
+- continue;
+-
+- /* Try to import the certificate. This may fail for legitimate reasons
+- such as duplicate certificate, which is allowed by MS but not
+- OpenSSL. */
+- if(X509_STORE_add_cert(store, x509) == 1) {
+-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+- infof(data, "SSL: Imported cert \"%s\"", cert_name);
+-#endif
+- imported_native_ca = true;
+- }
+- X509_free(x509);
+- }
+-
+- free(enhkey_usage);
+- CertFreeCertificateContext(pContext);
+- CertCloseStore(hStore, 0);
+-
+- if(result)
+- return result;
+- }
+- if(imported_native_ca)
+- infof(data, "successfully imported Windows CA store");
+- else
+- infof(data, "error importing Windows CA store, continuing anyway");
+- }
+-#endif
+-
+- if(ca_info_blob) {
+- result = load_cacert_from_memory(backend->ctx, ca_info_blob);
+- if(result) {
+- if(result == CURLE_OUT_OF_MEMORY ||
+- (verifypeer && !imported_native_ca)) {
+- failf(data, "error importing CA certificate blob");
+- return result;
+- }
+- /* Only warn if no certificate verification is required. */
+- infof(data, "error importing CA certificate blob, continuing anyway");
+- }
+- }
+-
+- if(verifypeer && !imported_native_ca && (ssl_cafile || ssl_capath)) {
+-#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
+- /* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */
+- if(ssl_cafile &&
+- !SSL_CTX_load_verify_file(backend->ctx, ssl_cafile)) {
+- /* Fail if we insist on successfully verifying the server. */
+- failf(data, "error setting certificate file: %s", ssl_cafile);
+- return CURLE_SSL_CACERT_BADFILE;
+- }
+- if(ssl_capath &&
+- !SSL_CTX_load_verify_dir(backend->ctx, ssl_capath)) {
+- /* Fail if we insist on successfully verifying the server. */
+- failf(data, "error setting certificate path: %s", ssl_capath);
+- return CURLE_SSL_CACERT_BADFILE;
+- }
+-#else
+- /* tell OpenSSL where to find CA certificates that are used to verify the
+- server's certificate. */
+- if(!SSL_CTX_load_verify_locations(backend->ctx, ssl_cafile, ssl_capath)) {
+- /* Fail if we insist on successfully verifying the server. */
+- failf(data, "error setting certificate verify locations:"
+- " CAfile: %s CApath: %s",
+- ssl_cafile ? ssl_cafile : "none",
+- ssl_capath ? ssl_capath : "none");
+- return CURLE_SSL_CACERT_BADFILE;
+- }
+-#endif
+- infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
+- infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
+- }
+-
+-#ifdef CURL_CA_FALLBACK
+- if(verifypeer &&
+- !ca_info_blob && !ssl_cafile && !ssl_capath && !imported_native_ca) {
+- /* verifying the peer without any CA certificates won't
+- work so use openssl's built-in default as fallback */
+- SSL_CTX_set_default_verify_paths(backend->ctx);
+- }
+-#endif
+-
+- if(ssl_crlfile) {
+- /* tell OpenSSL where to find CRL file that is used to check certificate
+- * revocation */
+- lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(backend->ctx),
+- X509_LOOKUP_file());
+- if(!lookup ||
+- (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) {
+- failf(data, "error loading CRL file: %s", ssl_crlfile);
+- return CURLE_SSL_CRL_BADFILE;
+- }
+- /* Everything is fine. */
+- infof(data, "successfully loaded CRL file:");
+- X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
+- X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
+-
+- infof(data, " CRLfile: %s", ssl_crlfile);
+- }
+-
+- if(verifypeer) {
+- /* Try building a chain using issuers in the trusted store first to avoid
+- problems with server-sent legacy intermediates. Newer versions of
+- OpenSSL do alternate chain checking by default but we do not know how to
+- determine that in a reliable manner.
+- https://rt.openssl.org/Ticket/Display.html?id=3621&user=guest&pass=guest
+- */
+-#if defined(X509_V_FLAG_TRUSTED_FIRST)
+- X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
+- X509_V_FLAG_TRUSTED_FIRST);
+-#endif
+-#ifdef X509_V_FLAG_PARTIAL_CHAIN
+- if(!SSL_SET_OPTION(no_partialchain) && !ssl_crlfile) {
+- /* Have intermediate certificates in the trust store be treated as
+- trust-anchors, in the same way as self-signed root CA certificates
+- are. This allows users to verify servers using the intermediate cert
+- only, instead of needing the whole chain.
+-
+- Due to OpenSSL bug https://github.com/openssl/openssl/issues/5081 we
+- cannot do partial chains with a CRL check.
+- */
+- X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
+- X509_V_FLAG_PARTIAL_CHAIN);
+- }
+-#endif
+- }
++ result = populate_x509_store(data, conn, sockindex);
++ if(result)
++ return result;
+
+ /* OpenSSL always tries to verify the peer, this only says whether it should
+ * fail to connect if the verification fails, or if it should continue
+--
+2.34.1
+
diff --git a/sdk/recipes/patches/libcurl/0003-openssl-pass-x509-store-to-be-populated.p b/sdk/recipes/patches/libcurl/0003-openssl-pass-x509-store-to-be-populated.p
new file mode 100644
index 0000000..f909bb1
--- /dev/null
+++ b/sdk/recipes/patches/libcurl/0003-openssl-pass-x509-store-to-be-populated.p
@@ -0,0 +1,174 @@
+diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
+index 981075838..d80f79921 100644
+--- lib/vtls/openssl.c
++++ lib/vtls/openssl.c
+@@ -2830,7 +2830,7 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
+ return res;
+ }
+
+-static CURLcode load_cacert_from_memory(SSL_CTX *ctx,
++static CURLcode load_cacert_from_memory(X509_STORE *store,
+ const struct curl_blob *ca_info_blob)
+ {
+ /* these need to be freed at the end */
+@@ -2839,16 +2839,11 @@ static CURLcode load_cacert_from_memory(SSL_CTX *ctx,
+
+ /* everything else is just a reference */
+ int i, count = 0;
+- X509_STORE *cts = NULL;
+ X509_INFO *itmp = NULL;
+
+ if(ca_info_blob->len > (size_t)INT_MAX)
+ return CURLE_SSL_CACERT_BADFILE;
+
+- cts = SSL_CTX_get_cert_store(ctx);
+- if(!cts)
+- return CURLE_OUT_OF_MEMORY;
+-
+ cbio = BIO_new_mem_buf(ca_info_blob->data, (int)ca_info_blob->len);
+ if(!cbio)
+ return CURLE_OUT_OF_MEMORY;
+@@ -2863,7 +2858,7 @@ static CURLcode load_cacert_from_memory(SSL_CTX *ctx,
+ for(i = 0; i < (int)sk_X509_INFO_num(inf); ++i) {
+ itmp = sk_X509_INFO_value(inf, i);
+ if(itmp->x509) {
+- if(X509_STORE_add_cert(cts, itmp->x509)) {
++ if(X509_STORE_add_cert(store, itmp->x509)) {
+ ++count;
+ }
+ else {
+@@ -2873,7 +2868,7 @@ static CURLcode load_cacert_from_memory(SSL_CTX *ctx,
+ }
+ }
+ if(itmp->crl) {
+- if(X509_STORE_add_crl(cts, itmp->crl)) {
++ if(X509_STORE_add_crl(store, itmp->crl)) {
+ ++count;
+ }
+ else {
+@@ -2892,7 +2887,8 @@ static CURLcode load_cacert_from_memory(SSL_CTX *ctx,
+ }
+
+ static CURLcode populate_x509_store(struct Curl_easy *data,
+- struct connectdata *conn, int sockindex)
++ struct connectdata *conn,
++ X509_STORE *store)
+ {
+ CURLcode result = CURLE_OK;
+ X509_LOOKUP *lookup = NULL;
+@@ -2903,10 +2899,11 @@ static CURLcode populate_x509_store(struct Curl_easy *data,
+ const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
+ const char * const ssl_crlfile = SSL_SET_OPTION(primary.CRLfile);
+ const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
+- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+- struct ssl_backend_data *backend = connssl->backend;
+ bool imported_native_ca = false;
+
++ if(!store)
++ return CURLE_OUT_OF_MEMORY;
++
+ #if defined(USE_WIN32_CRYPTO)
+ /* Import certificates from the Windows root certificate store if requested.
+ https://stackoverflow.com/questions/9507184/
+@@ -2914,7 +2911,6 @@ static CURLcode populate_x509_store(struct Curl_easy *data,
+ https://datatracker.ietf.org/doc/html/rfc5280 */
+ if((SSL_CONN_CONFIG(verifypeer) || SSL_CONN_CONFIG(verifyhost)) &&
+ (SSL_SET_OPTION(native_ca_store))) {
+- X509_STORE *store = SSL_CTX_get_cert_store(backend->ctx);
+ HCERTSTORE hStore = CertOpenSystemStore(0, TEXT("ROOT"));
+
+ if(hStore) {
+@@ -3053,7 +3049,7 @@ static CURLcode populate_x509_store(struct Curl_easy *data,
+ #endif
+
+ if(ca_info_blob) {
+- result = load_cacert_from_memory(backend->ctx, ca_info_blob);
++ result = load_cacert_from_memory(store, ca_info_blob);
+ if(result) {
+ if(result == CURLE_OUT_OF_MEMORY ||
+ (verifypeer && !imported_native_ca)) {
+@@ -3069,13 +3065,13 @@ static CURLcode populate_x509_store(struct Curl_easy *data,
+ #if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
+ /* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */
+ if(ssl_cafile &&
+- !SSL_CTX_load_verify_file(backend->ctx, ssl_cafile)) {
++ !X509_STORE_load_file(store, ssl_cafile)) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate file: %s", ssl_cafile);
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ if(ssl_capath &&
+- !SSL_CTX_load_verify_dir(backend->ctx, ssl_capath)) {
++ !X509_STORE_load_path(store, ssl_capath)) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate path: %s", ssl_capath);
+ return CURLE_SSL_CACERT_BADFILE;
+@@ -3083,7 +3079,7 @@ static CURLcode populate_x509_store(struct Curl_easy *data,
+ #else
+ /* tell OpenSSL where to find CA certificates that are used to verify the
+ server's certificate. */
+- if(!SSL_CTX_load_verify_locations(backend->ctx, ssl_cafile, ssl_capath)) {
++ if(!X509_STORE_load_locations(store, ssl_cafile, ssl_capath)) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate verify locations:"
+ " CAfile: %s CApath: %s",
+@@ -3101,15 +3097,14 @@ static CURLcode populate_x509_store(struct Curl_easy *data,
+ !ca_info_blob && !ssl_cafile && !ssl_capath && !imported_native_ca) {
+ /* verifying the peer without any CA certificates won't
+ work so use openssl's built-in default as fallback */
+- SSL_CTX_set_default_verify_paths(backend->ctx);
++ X509_STORE_set_default_paths(store);
+ }
+ #endif
+
+ if(ssl_crlfile) {
+ /* tell OpenSSL where to find CRL file that is used to check certificate
+ * revocation */
+- lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(backend->ctx),
+- X509_LOOKUP_file());
++ lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
+ if(!lookup ||
+ (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) {
+ failf(data, "error loading CRL file: %s", ssl_crlfile);
+@@ -3117,7 +3112,7 @@ static CURLcode populate_x509_store(struct Curl_easy *data,
+ }
+ /* Everything is fine. */
+ infof(data, "successfully loaded CRL file:");
+- X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
++ X509_STORE_set_flags(store,
+ X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
+
+ infof(data, " CRLfile: %s", ssl_crlfile);
+@@ -3131,8 +3126,7 @@ static CURLcode populate_x509_store(struct Curl_easy *data,
+ https://rt.openssl.org/Ticket/Display.html?id=3621&user=guest&pass=guest
+ */
+ #if defined(X509_V_FLAG_TRUSTED_FIRST)
+- X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
+- X509_V_FLAG_TRUSTED_FIRST);
++ X509_STORE_set_flags(store, X509_V_FLAG_TRUSTED_FIRST);
+ #endif
+ #ifdef X509_V_FLAG_PARTIAL_CHAIN
+ if(!SSL_SET_OPTION(no_partialchain) && !ssl_crlfile) {
+@@ -3144,8 +3138,7 @@ static CURLcode populate_x509_store(struct Curl_easy *data,
+ Due to OpenSSL bug https://github.com/openssl/openssl/issues/5081 we
+ cannot do partial chains with a CRL check.
+ */
+- X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
+- X509_V_FLAG_PARTIAL_CHAIN);
++ X509_STORE_set_flags(store, X509_V_FLAG_PARTIAL_CHAIN);
+ }
+ #endif
+ }
+@@ -3450,7 +3443,8 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
+ }
+ #endif
+
+- result = populate_x509_store(data, conn, sockindex);
++ result = populate_x509_store(data, conn,
++ SSL_CTX_get_cert_store(backend->ctx));
+ if(result)
+ return result;
+
+--
+2.34.1
+
diff --git a/sdk/recipes/patches/libcurl/0004-urldata-fix-multi-handle-comment.p b/sdk/recipes/patches/libcurl/0004-urldata-fix-multi-handle-comment.p
new file mode 100644
index 0000000..7bdf402
--- /dev/null
+++ b/sdk/recipes/patches/libcurl/0004-urldata-fix-multi-handle-comment.p
@@ -0,0 +1,16 @@
+diff --git a/lib/urldata.h b/lib/urldata.h
+index f5bd5a3e9..aba07c275 100644
+--- lib/urldata.h
++++ lib/urldata.h
+@@ -1531,7 +1531,7 @@ struct UrlState {
+ * Character pointer fields point to dynamic storage, unless otherwise stated.
+ */
+
+-struct Curl_multi; /* declared and used only in multi.c */
++struct Curl_multi; /* declared in multihandle.c */
+
+ /*
+ * This enumeration MUST not use conditional directives (#ifdefs), new
+--
+2.34.1
+
diff --git a/sdk/recipes/patches/libcurl/0005-multi-vtls-enable-ssl-backend-specific-storage-on-mu.p b/sdk/recipes/patches/libcurl/0005-multi-vtls-enable-ssl-backend-specific-storage-on-mu.p
new file mode 100644
index 0000000..d961322
--- /dev/null
+++ b/sdk/recipes/patches/libcurl/0005-multi-vtls-enable-ssl-backend-specific-storage-on-mu.p
@@ -0,0 +1,245 @@
+diff --git a/lib/multi.c b/lib/multi.c
+index 51acba73a..09965de83 100644
+--- lib/multi.c
++++ lib/multi.c
+@@ -2770,6 +2770,11 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
+ wakeup_close(multi->wakeup_pair[1]);
+ #endif
+ #endif
++
++#ifdef USE_SSL
++ Curl_free_multi_ssl_backend_data(multi->ssl_backend_data);
++#endif
++
+ free(multi);
+
+ return CURLM_OK;
+diff --git a/lib/multihandle.h b/lib/multihandle.h
+index a997784ea..5a83656d5 100644
+--- lib/multihandle.h
++++ lib/multihandle.h
+@@ -79,6 +79,10 @@ typedef enum {
+ /* value for MAXIMUM CONCURRENT STREAMS upper limit */
+ #define INITIAL_MAX_CONCURRENT_STREAMS ((1U << 31) - 1)
+
++/* Curl_multi SSL backend-specific data; declared differently by each SSL
++ backend */
++struct multi_ssl_backend_data;
++
+ /* This is the struct known as CURLM on the outside */
+ struct Curl_multi {
+ /* First a simple identifier to easier detect if a user mix up
+@@ -118,6 +122,10 @@ struct Curl_multi {
+ times of all currently set timers */
+ struct Curl_tree *timetree;
+
++#if defined(USE_SSL)
++ struct multi_ssl_backend_data *ssl_backend_data;
++#endif
++
+ /* 'sockhash' is the lookup hash for socket descriptor => easy handles (note
+ the pluralis form, there can be more than one easy handle waiting on the
+ same actual socket) */
+diff --git a/lib/vtls/bearssl.c b/lib/vtls/bearssl.c
+index 1221ce8c8..e66dd8469 100644
+--- lib/vtls/bearssl.c
++++ lib/vtls/bearssl.c
+@@ -1208,7 +1208,8 @@ const struct Curl_ssl Curl_ssl_bearssl = {
+ Curl_none_false_start, /* false_start */
+ bearssl_sha256sum, /* sha256sum */
+ NULL, /* associate_connection */
+- NULL /* disassociate_connection */
++ NULL, /* disassociate_connection */
++ NULL /* free_multi_ssl_backend_data */
+ };
+
+ #endif /* USE_BEARSSL */
+diff --git a/lib/vtls/gskit.c b/lib/vtls/gskit.c
+index 4ee4edea6..18bd47919 100644
+--- lib/vtls/gskit.c
++++ lib/vtls/gskit.c
+@@ -1323,7 +1323,8 @@ const struct Curl_ssl Curl_ssl_gskit = {
+ Curl_none_false_start, /* false_start */
+ NULL, /* sha256sum */
+ NULL, /* associate_connection */
+- NULL /* disassociate_connection */
++ NULL, /* disassociate_connection */
++ NULL /* free_multi_ssl_backend_data */
+ };
+
+ #endif /* USE_GSKIT */
+diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
+index cf3dbc523..68e3fe299 100644
+--- lib/vtls/gtls.c
++++ lib/vtls/gtls.c
+@@ -1699,7 +1699,8 @@ const struct Curl_ssl Curl_ssl_gnutls = {
+ Curl_none_false_start, /* false_start */
+ gtls_sha256sum, /* sha256sum */
+ NULL, /* associate_connection */
+- NULL /* disassociate_connection */
++ NULL, /* disassociate_connection */
++ NULL /* free_multi_ssl_backend_data */
+ };
+
+ #endif /* USE_GNUTLS */
+diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c
+index fbde8976e..a5250289d 100644
+--- lib/vtls/mbedtls.c
++++ lib/vtls/mbedtls.c
+@@ -1267,7 +1267,8 @@ const struct Curl_ssl Curl_ssl_mbedtls = {
+ Curl_none_false_start, /* false_start */
+ mbedtls_sha256sum, /* sha256sum */
+ NULL, /* associate_connection */
+- NULL /* disassociate_connection */
++ NULL, /* disassociate_connection */
++ NULL /* free_multi_ssl_backend_data */
+ };
+
+ #endif /* USE_MBEDTLS */
+diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
+index b08808c43..55d777d69 100644
+--- lib/vtls/nss.c
++++ lib/vtls/nss.c
+@@ -2530,7 +2530,8 @@ const struct Curl_ssl Curl_ssl_nss = {
+ nss_false_start, /* false_start */
+ nss_sha256sum, /* sha256sum */
+ NULL, /* associate_connection */
+- NULL /* disassociate_connection */
++ NULL, /* disassociate_connection */
++ NULL /* free_multi_ssl_backend_data */
+ };
+
+ #endif /* USE_NSS */
+diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
+index d80f79921..b536b42da 100644
+--- lib/vtls/openssl.c
++++ lib/vtls/openssl.c
+@@ -4619,7 +4619,8 @@ const struct Curl_ssl Curl_ssl_openssl = {
+ NULL, /* sha256sum */
+ #endif
+ ossl_associate_connection, /* associate_connection */
+- ossl_disassociate_connection /* disassociate_connection */
++ ossl_disassociate_connection, /* disassociate_connection */
++ NULL /* free_multi_ssl_backend_data */
+ };
+
+ #endif /* USE_OPENSSL */
+diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c
+index 77a49f1ab..45433bb85 100644
+--- lib/vtls/rustls.c
++++ lib/vtls/rustls.c
+@@ -630,7 +630,8 @@ const struct Curl_ssl Curl_ssl_rustls = {
+ Curl_none_false_start, /* false_start */
+ NULL, /* sha256sum */
+ NULL, /* associate_connection */
+- NULL /* disassociate_connection */
++ NULL, /* disassociate_connection */
++ NULL /* free_multi_ssl_backend_data */
+ };
+
+ #endif /* USE_RUSTLS */
+diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
+index fcfb9c6df..1e6a93106 100644
+--- lib/vtls/schannel.c
++++ lib/vtls/schannel.c
+@@ -2809,7 +2809,8 @@ const struct Curl_ssl Curl_ssl_schannel = {
+ Curl_none_false_start, /* false_start */
+ schannel_sha256sum, /* sha256sum */
+ NULL, /* associate_connection */
+- NULL /* disassociate_connection */
++ NULL, /* disassociate_connection */
++ NULL /* free_multi_ssl_backend_data */
+ };
+
+ #endif /* USE_SCHANNEL */
+diff --git a/lib/vtls/sectransp.c b/lib/vtls/sectransp.c
+index d44f14ba6..d27adedca 100644
+--- lib/vtls/sectransp.c
++++ lib/vtls/sectransp.c
+@@ -3531,7 +3531,8 @@ const struct Curl_ssl Curl_ssl_sectransp = {
+ sectransp_false_start, /* false_start */
+ sectransp_sha256sum, /* sha256sum */
+ NULL, /* associate_connection */
+- NULL /* disassociate_connection */
++ NULL, /* disassociate_connection */
++ NULL /* free_multi_ssl_backend_data */
+ };
+
+ #ifdef __clang__
+diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
+index 9dee5aa3b..8a251b270 100644
+--- lib/vtls/vtls.c
++++ lib/vtls/vtls.c
+@@ -655,6 +655,12 @@ void Curl_ssl_detach_conn(struct Curl_easy *data,
+ }
+ }
+
++void Curl_free_multi_ssl_backend_data(struct multi_ssl_backend_data *mbackend)
++{
++ if(Curl_ssl->free_multi_ssl_backend_data && mbackend)
++ Curl_ssl->free_multi_ssl_backend_data(mbackend);
++}
++
+ void Curl_ssl_close_all(struct Curl_easy *data)
+ {
+ /* kill the session ID cache if not shared */
+@@ -1310,7 +1316,8 @@ static const struct Curl_ssl Curl_ssl_multi = {
+ Curl_none_false_start, /* false_start */
+ NULL, /* sha256sum */
+ NULL, /* associate_connection */
+- NULL /* disassociate_connection */
++ NULL, /* disassociate_connection */
++ NULL /* free_multi_ssl_backend_data */
+ };
+
+ const struct Curl_ssl *Curl_ssl =
+diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h
+index 50c53b3fb..1ab90c09e 100644
+--- lib/vtls/vtls.h
++++ lib/vtls/vtls.h
+@@ -47,6 +47,10 @@ struct ssl_connect_data;
+ #define VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR \
+ ALPN_ACCEPTED "%.*s"
+
++/* Curl_multi SSL backend-specific data; declared differently by each SSL
++ backend */
++struct multi_ssl_backend_data;
++
+ struct Curl_ssl {
+ /*
+ * This *must* be the first entry to allow returning the list of available
+@@ -102,6 +106,8 @@ struct Curl_ssl {
+ struct connectdata *conn,
+ int sockindex);
+ void (*disassociate_connection)(struct Curl_easy *data, int sockindex);
++
++ void (*free_multi_ssl_backend_data)(struct multi_ssl_backend_data *mbackend);
+ };
+
+ #ifdef USE_SSL
+@@ -311,6 +317,8 @@ void Curl_ssl_associate_conn(struct Curl_easy *data,
+ void Curl_ssl_detach_conn(struct Curl_easy *data,
+ struct connectdata *conn);
+
++void Curl_free_multi_ssl_backend_data(struct multi_ssl_backend_data *mbackend);
++
+ #define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */
+
+ #else /* if not USE_SSL */
+diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c
+index 594c39a32..bc2a3c03f 100644
+--- lib/vtls/wolfssl.c
++++ lib/vtls/wolfssl.c
+@@ -1241,7 +1241,8 @@ const struct Curl_ssl Curl_ssl_wolfssl = {
+ Curl_none_false_start, /* false_start */
+ wolfssl_sha256sum, /* sha256sum */
+ NULL, /* associate_connection */
+- NULL /* disassociate_connection */
++ NULL, /* disassociate_connection */
++ NULL /* free_multi_ssl_backend_data */
+ };
+
+ #endif
+--
+2.34.1
+
diff --git a/sdk/recipes/patches/libcurl/0006-openssl-cache-x509-store-on-multi-handle.p b/sdk/recipes/patches/libcurl/0006-openssl-cache-x509-store-on-multi-handle.p
new file mode 100644
index 0000000..da158e6
--- /dev/null
+++ b/sdk/recipes/patches/libcurl/0006-openssl-cache-x509-store-on-multi-handle.p
@@ -0,0 +1,202 @@
+diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
+index b536b42da..6749b4be3 100644
+--- lib/vtls/openssl.c
++++ lib/vtls/openssl.c
+@@ -110,6 +110,10 @@
+ #include <openssl/ui.h>
+ #endif
+
++#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
++#define HAVE_THREADS
++#endif
++
+ #if OPENSSL_VERSION_NUMBER >= 0x00909000L
+ #define SSL_METHOD_QUAL const
+ #else
+@@ -259,6 +263,15 @@
+ #define HAVE_OPENSSL_VERSION
+ #endif
+
++/*
++ * Whether the OpenSSL version has the API needed to support sharing an
++ * X509_STORE between connections. The API is:
++ * * `X509_STORE_up_ref` -- Introduced: OpenSSL 1.1.0.
++ */
++#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* OpenSSL >= 1.1.0 */
++#define HAVE_SSL_X509_STORE_SHARE
++#endif
++
+ struct ssl_backend_data {
+ struct Curl_easy *logger; /* transfer handle to pass trace logs to, only
+ using sockindex 0 */
+@@ -272,6 +285,13 @@ struct ssl_backend_data {
+ #endif
+ };
+
++#if defined(HAVE_SSL_X509_STORE_SHARE)
++struct multi_ssl_backend_data {
++ char *CAfile; /* CAfile path used to generate X509 store */
++ X509_STORE *store; /* cached X509 store or NULL if none */
++};
++#endif /* HAVE_SSL_X509_STORE_SHARE */
++
+ #define push_certinfo(_label, _num) \
+ do { \
+ long info_len = BIO_get_mem_data(mem, &ptr); \
+@@ -3146,6 +3166,113 @@ static CURLcode populate_x509_store(struct Curl_easy *data,
+ return result;
+ }
+
++#if defined(HAVE_SSL_X509_STORE_SHARE)
++static bool cached_x509_store_different(
++ const struct multi_ssl_backend_data *mb,
++ const struct connectdata *conn)
++{
++ if(!mb->CAfile || !SSL_CONN_CONFIG(CAfile))
++ return mb->CAfile != SSL_CONN_CONFIG(CAfile);
++
++ return strcmp(mb->CAfile, SSL_CONN_CONFIG(CAfile));
++}
++
++static X509_STORE *get_cached_x509_store(const struct Curl_easy *data,
++ const struct connectdata *conn)
++{
++ struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi;
++ X509_STORE *store = NULL;
++
++ if(multi &&
++ multi->ssl_backend_data &&
++ multi->ssl_backend_data->store &&
++ !cached_x509_store_different(multi->ssl_backend_data, conn)) {
++ store = multi->ssl_backend_data->store;
++ }
++
++ return store;
++}
++
++static void set_cached_x509_store(const struct Curl_easy *data,
++ const struct connectdata *conn,
++ X509_STORE *store)
++{
++ struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi;
++ struct multi_ssl_backend_data *mbackend;
++
++ if(!multi)
++ return;
++
++ if(!multi->ssl_backend_data) {
++ multi->ssl_backend_data = calloc(1, sizeof(struct multi_ssl_backend_data));
++ if(!multi->ssl_backend_data)
++ return;
++ }
++
++ mbackend = multi->ssl_backend_data;
++
++ if(X509_STORE_up_ref(store)) {
++ char *CAfile = NULL;
++
++ if(SSL_CONN_CONFIG(CAfile)) {
++ CAfile = strdup(SSL_CONN_CONFIG(CAfile));
++ if(!CAfile) {
++ X509_STORE_free(store);
++ return;
++ }
++ }
++
++ if(mbackend->store) {
++ X509_STORE_free(mbackend->store);
++ free(mbackend->CAfile);
++ }
++
++ mbackend->store = store;
++ mbackend->CAfile = CAfile;
++ }
++}
++
++static CURLcode set_up_x509_store(struct Curl_easy *data,
++ struct connectdata *conn,
++ struct ssl_backend_data *backend)
++{
++ CURLcode result = CURLE_OK;
++ X509_STORE *cached_store = get_cached_x509_store(data, conn);
++
++ /* Consider the X509 store cacheable if it comes exclusively from a CAfile,
++ or no source is provided and we are falling back to openssl's built-in
++ default. */
++ bool cache_criteria_met = SSL_CONN_CONFIG(verifypeer) &&
++ !SSL_CONN_CONFIG(CApath) &&
++ !SSL_CONN_CONFIG(ca_info_blob) &&
++ !SSL_SET_OPTION(primary.CRLfile) &&
++ !SSL_SET_OPTION(native_ca_store);
++
++ if(cached_store && cache_criteria_met && X509_STORE_up_ref(cached_store)) {
++ SSL_CTX_set_cert_store(backend->ctx, cached_store);
++ }
++ else {
++ X509_STORE *store = SSL_CTX_get_cert_store(backend->ctx);
++
++ result = populate_x509_store(data, conn, store);
++ if(result == CURLE_OK && cache_criteria_met) {
++ set_cached_x509_store(data, conn, store);
++ }
++ }
++
++ return result;
++}
++#else /* HAVE_SSL_X509_STORE_SHARE */
++static CURLcode set_up_x509_store(struct Curl_easy *data,
++ struct connectdata *conn,
++ struct ssl_backend_data *backend)
++{
++ X509_STORE *store = SSL_CTX_get_cert_store(backend->ctx);
++
++ return populate_x509_store(data, conn, store);
++}
++#endif /* HAVE_SSL_X509_STORE_SHARE */
++
+ static CURLcode ossl_connect_step1(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
+ {
+@@ -3443,8 +3570,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
+ }
+ #endif
+
+- result = populate_x509_store(data, conn,
+- SSL_CTX_get_cert_store(backend->ctx));
++ result = set_up_x509_store(data, conn, backend);
+ if(result)
+ return result;
+
+@@ -4579,6 +4705,20 @@ static void ossl_disassociate_connection(struct Curl_easy *data,
+ }
+ }
+
++static void ossl_free_multi_ssl_backend_data(
++ struct multi_ssl_backend_data *mbackend)
++{
++#if defined(HAVE_SSL_X509_STORE_SHARE)
++ if(mbackend->store) {
++ X509_STORE_free(mbackend->store);
++ }
++ free(mbackend->CAfile);
++ free(mbackend);
++#else /* HAVE_SSL_X509_STORE_SHARE */
++ (void)mbackend;
++#endif /* HAVE_SSL_X509_STORE_SHARE */
++}
++
+ const struct Curl_ssl Curl_ssl_openssl = {
+ { CURLSSLBACKEND_OPENSSL, "openssl" }, /* info */
+
+@@ -4620,7 +4760,7 @@ const struct Curl_ssl Curl_ssl_openssl = {
+ #endif
+ ossl_associate_connection, /* associate_connection */
+ ossl_disassociate_connection, /* disassociate_connection */
+- NULL /* free_multi_ssl_backend_data */
++ ossl_free_multi_ssl_backend_data /* free_multi_ssl_backend_data */
+ };
+
+ #endif /* USE_OPENSSL */
+--
+2.34.1
+
diff --git a/sdk/recipes/patches/libcurl/0007-openssl-use-new-x509-store-if-cached-is-24h-old.p b/sdk/recipes/patches/libcurl/0007-openssl-use-new-x509-store-if-cached-is-24h-old.p
new file mode 100644
index 0000000..d9c9c77
--- /dev/null
+++ b/sdk/recipes/patches/libcurl/0007-openssl-use-new-x509-store-if-cached-is-24h-old.p
@@ -0,0 +1,50 @@
+diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
+index 6749b4be3..9c752554e 100644
+--- lib/vtls/openssl.c
++++ lib/vtls/openssl.c
+@@ -287,8 +287,9 @@ struct ssl_backend_data {
+
+ #if defined(HAVE_SSL_X509_STORE_SHARE)
+ struct multi_ssl_backend_data {
+- char *CAfile; /* CAfile path used to generate X509 store */
+- X509_STORE *store; /* cached X509 store or NULL if none */
++ char *CAfile; /* CAfile path used to generate X509 store */
++ X509_STORE *store; /* cached X509 store or NULL if none */
++ struct curltime time; /* when the cached store was created */
+ };
+ #endif /* HAVE_SSL_X509_STORE_SHARE */
+
+@@ -3167,6 +3168,14 @@ static CURLcode populate_x509_store(struct Curl_easy *data,
+ }
+
+ #if defined(HAVE_SSL_X509_STORE_SHARE)
++#define X509_STORE_EXPIRY_MS (24 * 60 * 60 * 1000) /* 24 hours */
++static bool cached_x509_store_expired(const struct multi_ssl_backend_data *mb)
++{
++ struct curltime now = Curl_now();
++
++ return Curl_timediff(now, mb->time) >= X509_STORE_EXPIRY_MS;
++}
++
+ static bool cached_x509_store_different(
+ const struct multi_ssl_backend_data *mb,
+ const struct connectdata *conn)
+@@ -3186,6 +3195,7 @@ static X509_STORE *get_cached_x509_store(const struct Curl_easy *data,
+ if(multi &&
+ multi->ssl_backend_data &&
+ multi->ssl_backend_data->store &&
++ !cached_x509_store_expired(multi->ssl_backend_data) &&
+ !cached_x509_store_different(multi->ssl_backend_data, conn)) {
+ store = multi->ssl_backend_data->store;
+ }
+@@ -3227,6 +3237,7 @@ static void set_cached_x509_store(const struct Curl_easy *data,
+ free(mbackend->CAfile);
+ }
+
++ mbackend->time = Curl_now();
+ mbackend->store = store;
+ mbackend->CAfile = CAfile;
+ }
+--
+2.34.1
+
-----------------------------------------------------------------------
Summary of changes:
.../0002-openssl-split-out-x509-store-loading.p | 554 ++++++++++++++++++++
.../0003-openssl-pass-x509-store-to-be-populated.p | 174 ++++++
.../0004-urldata-fix-multi-handle-comment.p | 16 +
...tls-enable-ssl-backend-specific-storage-on-mu.p | 245 +++++++++
...0006-openssl-cache-x509-store-on-multi-handle.p | 202 +++++++
...enssl-use-new-x509-store-if-cached-is-24h-old.p | 50 ++
6 files changed, 1241 insertions(+)
create mode 100644 sdk/recipes/patches/libcurl/0002-openssl-split-out-x509-store-loading.p
create mode 100644 sdk/recipes/patches/libcurl/0003-openssl-pass-x509-store-to-be-populated.p
create mode 100644 sdk/recipes/patches/libcurl/0004-urldata-fix-multi-handle-comment.p
create mode 100644 sdk/recipes/patches/libcurl/0005-multi-vtls-enable-ssl-backend-specific-storage-on-mu.p
create mode 100644 sdk/recipes/patches/libcurl/0006-openssl-cache-x509-store-on-multi-handle.p
create mode 100644 sdk/recipes/patches/libcurl/0007-openssl-use-new-x509-store-if-cached-is-24h-old.p
diff --git a/sdk/recipes/patches/libcurl/0002-openssl-split-out-x509-store-loading.p b/sdk/recipes/patches/libcurl/0002-openssl-split-out-x509-store-loading.p
new file mode 100644
index 0000000..658c801
--- /dev/null
+++ b/sdk/recipes/patches/libcurl/0002-openssl-split-out-x509-store-loading.p
@@ -0,0 +1,554 @@
+diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
+index ad2efa558..981075838 100644
+--- lib/vtls/openssl.c
++++ lib/vtls/openssl.c
+@@ -2891,13 +2891,274 @@ static CURLcode load_cacert_from_memory(SSL_CTX *ctx,
+ return (count > 0 ? CURLE_OK : CURLE_SSL_CACERT_BADFILE);
+ }
+
++static CURLcode populate_x509_store(struct Curl_easy *data,
++ struct connectdata *conn, int sockindex)
++{
++ CURLcode result = CURLE_OK;
++ X509_LOOKUP *lookup = NULL;
++ const struct curl_blob *ca_info_blob = SSL_CONN_CONFIG(ca_info_blob);
++ const char * const ssl_cafile =
++ /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
++ (ca_info_blob ? NULL : SSL_CONN_CONFIG(CAfile));
++ const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
++ const char * const ssl_crlfile = SSL_SET_OPTION(primary.CRLfile);
++ const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
++ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
++ struct ssl_backend_data *backend = connssl->backend;
++ bool imported_native_ca = false;
++
++#if defined(USE_WIN32_CRYPTO)
++ /* Import certificates from the Windows root certificate store if requested.
++ https://stackoverflow.com/questions/9507184/
++ https://github.com/d3x0r/SACK/blob/master/src/netlib/ssl_layer.c#L1037
++ https://datatracker.ietf.org/doc/html/rfc5280 */
++ if((SSL_CONN_CONFIG(verifypeer) || SSL_CONN_CONFIG(verifyhost)) &&
++ (SSL_SET_OPTION(native_ca_store))) {
++ X509_STORE *store = SSL_CTX_get_cert_store(backend->ctx);
++ HCERTSTORE hStore = CertOpenSystemStore(0, TEXT("ROOT"));
++
++ if(hStore) {
++ PCCERT_CONTEXT pContext = NULL;
++ /* The array of enhanced key usage OIDs will vary per certificate and is
++ declared outside of the loop so that rather than malloc/free each
++ iteration we can grow it with realloc, when necessary. */
++ CERT_ENHKEY_USAGE *enhkey_usage = NULL;
++ DWORD enhkey_usage_size = 0;
++
++ /* This loop makes a best effort to import all valid certificates from
++ the MS root store. If a certificate cannot be imported it is skipped.
++ 'result' is used to store only hard-fail conditions (such as out of
++ memory) that cause an early break. */
++ result = CURLE_OK;
++ for(;;) {
++ X509 *x509;
++ FILETIME now;
++ BYTE key_usage[2];
++ DWORD req_size;
++ const unsigned char *encoded_cert;
++#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
++ char cert_name[256];
++#endif
++
++ pContext = CertEnumCertificatesInStore(hStore, pContext);
++ if(!pContext)
++ break;
++
++#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
++ if(!CertGetNameStringA(pContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
++ NULL, cert_name, sizeof(cert_name))) {
++ strcpy(cert_name, "Unknown");
++ }
++ infof(data, "SSL: Checking cert \"%s\"", cert_name);
++#endif
++
++ encoded_cert = (const unsigned char *)pContext->pbCertEncoded;
++ if(!encoded_cert)
++ continue;
++
++ GetSystemTimeAsFileTime(&now);
++ if(CompareFileTime(&pContext->pCertInfo->NotBefore, &now) > 0 ||
++ CompareFileTime(&now, &pContext->pCertInfo->NotAfter) > 0)
++ continue;
++
++ /* If key usage exists check for signing attribute */
++ if(CertGetIntendedKeyUsage(pContext->dwCertEncodingType,
++ pContext->pCertInfo,
++ key_usage, sizeof(key_usage))) {
++ if(!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE))
++ continue;
++ }
++ else if(GetLastError())
++ continue;
++
++ /* If enhanced key usage exists check for server auth attribute.
++ *
++ * Note "In a Microsoft environment, a certificate might also have EKU
++ * extended properties that specify valid uses for the certificate."
++ * The call below checks both, and behavior varies depending on what is
++ * found. For more details see CertGetEnhancedKeyUsage doc.
++ */
++ if(CertGetEnhancedKeyUsage(pContext, 0, NULL, &req_size)) {
++ if(req_size && req_size > enhkey_usage_size) {
++ void *tmp = realloc(enhkey_usage, req_size);
++
++ if(!tmp) {
++ failf(data, "SSL: Out of memory allocating for OID list");
++ result = CURLE_OUT_OF_MEMORY;
++ break;
++ }
++
++ enhkey_usage = (CERT_ENHKEY_USAGE *)tmp;
++ enhkey_usage_size = req_size;
++ }
++
++ if(CertGetEnhancedKeyUsage(pContext, 0, enhkey_usage, &req_size)) {
++ if(!enhkey_usage->cUsageIdentifier) {
++ /* "If GetLastError returns CRYPT_E_NOT_FOUND, the certificate is
++ good for all uses. If it returns zero, the certificate has no
++ valid uses." */
++ if((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND)
++ continue;
++ }
++ else {
++ DWORD i;
++ bool found = false;
++
++ for(i = 0; i < enhkey_usage->cUsageIdentifier; ++i) {
++ if(!strcmp("1.3.6.1.5.5.7.3.1" /* OID server auth */,
++ enhkey_usage->rgpszUsageIdentifier[i])) {
++ found = true;
++ break;
++ }
++ }
++
++ if(!found)
++ continue;
++ }
++ }
++ else
++ continue;
++ }
++ else
++ continue;
++
++ x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded);
++ if(!x509)
++ continue;
++
++ /* Try to import the certificate. This may fail for legitimate reasons
++ such as duplicate certificate, which is allowed by MS but not
++ OpenSSL. */
++ if(X509_STORE_add_cert(store, x509) == 1) {
++#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
++ infof(data, "SSL: Imported cert \"%s\"", cert_name);
++#endif
++ imported_native_ca = true;
++ }
++ X509_free(x509);
++ }
++
++ free(enhkey_usage);
++ CertFreeCertificateContext(pContext);
++ CertCloseStore(hStore, 0);
++
++ if(result)
++ return result;
++ }
++ if(imported_native_ca)
++ infof(data, "successfully imported Windows CA store");
++ else
++ infof(data, "error importing Windows CA store, continuing anyway");
++ }
++#endif
++
++ if(ca_info_blob) {
++ result = load_cacert_from_memory(backend->ctx, ca_info_blob);
++ if(result) {
++ if(result == CURLE_OUT_OF_MEMORY ||
++ (verifypeer && !imported_native_ca)) {
++ failf(data, "error importing CA certificate blob");
++ return result;
++ }
++ /* Only warn if no certificate verification is required. */
++ infof(data, "error importing CA certificate blob, continuing anyway");
++ }
++ }
++
++ if(verifypeer && !imported_native_ca && (ssl_cafile || ssl_capath)) {
++#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
++ /* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */
++ if(ssl_cafile &&
++ !SSL_CTX_load_verify_file(backend->ctx, ssl_cafile)) {
++ /* Fail if we insist on successfully verifying the server. */
++ failf(data, "error setting certificate file: %s", ssl_cafile);
++ return CURLE_SSL_CACERT_BADFILE;
++ }
++ if(ssl_capath &&
++ !SSL_CTX_load_verify_dir(backend->ctx, ssl_capath)) {
++ /* Fail if we insist on successfully verifying the server. */
++ failf(data, "error setting certificate path: %s", ssl_capath);
++ return CURLE_SSL_CACERT_BADFILE;
++ }
++#else
++ /* tell OpenSSL where to find CA certificates that are used to verify the
++ server's certificate. */
++ if(!SSL_CTX_load_verify_locations(backend->ctx, ssl_cafile, ssl_capath)) {
++ /* Fail if we insist on successfully verifying the server. */
++ failf(data, "error setting certificate verify locations:"
++ " CAfile: %s CApath: %s",
++ ssl_cafile ? ssl_cafile : "none",
++ ssl_capath ? ssl_capath : "none");
++ return CURLE_SSL_CACERT_BADFILE;
++ }
++#endif
++ infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
++ infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
++ }
++
++#ifdef CURL_CA_FALLBACK
++ if(verifypeer &&
++ !ca_info_blob && !ssl_cafile && !ssl_capath && !imported_native_ca) {
++ /* verifying the peer without any CA certificates won't
++ work so use openssl's built-in default as fallback */
++ SSL_CTX_set_default_verify_paths(backend->ctx);
++ }
++#endif
++
++ if(ssl_crlfile) {
++ /* tell OpenSSL where to find CRL file that is used to check certificate
++ * revocation */
++ lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(backend->ctx),
++ X509_LOOKUP_file());
++ if(!lookup ||
++ (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) {
++ failf(data, "error loading CRL file: %s", ssl_crlfile);
++ return CURLE_SSL_CRL_BADFILE;
++ }
++ /* Everything is fine. */
++ infof(data, "successfully loaded CRL file:");
++ X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
++ X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
++
++ infof(data, " CRLfile: %s", ssl_crlfile);
++ }
++
++ if(verifypeer) {
++ /* Try building a chain using issuers in the trusted store first to avoid
++ problems with server-sent legacy intermediates. Newer versions of
++ OpenSSL do alternate chain checking by default but we do not know how to
++ determine that in a reliable manner.
++ https://rt.openssl.org/Ticket/Display.html?id=3621&user=guest&pass=guest
++ */
++#if defined(X509_V_FLAG_TRUSTED_FIRST)
++ X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
++ X509_V_FLAG_TRUSTED_FIRST);
++#endif
++#ifdef X509_V_FLAG_PARTIAL_CHAIN
++ if(!SSL_SET_OPTION(no_partialchain) && !ssl_crlfile) {
++ /* Have intermediate certificates in the trust store be treated as
++ trust-anchors, in the same way as self-signed root CA certificates
++ are. This allows users to verify servers using the intermediate cert
++ only, instead of needing the whole chain.
++
++ Due to OpenSSL bug https://github.com/openssl/openssl/issues/5081 we
++ cannot do partial chains with a CRL check.
++ */
++ X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
++ X509_V_FLAG_PARTIAL_CHAIN);
++ }
++#endif
++ }
++
++ return result;
++}
++
+ static CURLcode ossl_connect_step1(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
+ {
+ CURLcode result = CURLE_OK;
+ char *ciphers;
+ SSL_METHOD_QUAL SSL_METHOD *req_method = NULL;
+- X509_LOOKUP *lookup = NULL;
+ curl_socket_t sockfd = conn->sock[sockindex];
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ ctx_option_t ctx_options = 0;
+@@ -2919,17 +3180,10 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
+ #endif
+ char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);
+ const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob);
+- const struct curl_blob *ca_info_blob = SSL_CONN_CONFIG(ca_info_blob);
+ const char * const ssl_cert_type = SSL_SET_OPTION(cert_type);
+- const char * const ssl_cafile =
+- /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
+- (ca_info_blob ? NULL : SSL_CONN_CONFIG(CAfile));
+- const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
+ const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
+- const char * const ssl_crlfile = SSL_SET_OPTION(primary.CRLfile);
+ char error_buffer[256];
+ struct ssl_backend_data *backend = connssl->backend;
+- bool imported_native_ca = false;
+
+ DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
+ DEBUGASSERT(backend);
+@@ -3196,249 +3450,9 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
+ }
+ #endif
+
+-
+-#if defined(USE_WIN32_CRYPTO)
+- /* Import certificates from the Windows root certificate store if requested.
+- https://stackoverflow.com/questions/9507184/
+- https://github.com/d3x0r/SACK/blob/master/src/netlib/ssl_layer.c#L1037
+- https://datatracker.ietf.org/doc/html/rfc5280 */
+- if((SSL_CONN_CONFIG(verifypeer) || SSL_CONN_CONFIG(verifyhost)) &&
+- (SSL_SET_OPTION(native_ca_store))) {
+- X509_STORE *store = SSL_CTX_get_cert_store(backend->ctx);
+- HCERTSTORE hStore = CertOpenSystemStore(0, TEXT("ROOT"));
+-
+- if(hStore) {
+- PCCERT_CONTEXT pContext = NULL;
+- /* The array of enhanced key usage OIDs will vary per certificate and is
+- declared outside of the loop so that rather than malloc/free each
+- iteration we can grow it with realloc, when necessary. */
+- CERT_ENHKEY_USAGE *enhkey_usage = NULL;
+- DWORD enhkey_usage_size = 0;
+-
+- /* This loop makes a best effort to import all valid certificates from
+- the MS root store. If a certificate cannot be imported it is skipped.
+- 'result' is used to store only hard-fail conditions (such as out of
+- memory) that cause an early break. */
+- result = CURLE_OK;
+- for(;;) {
+- X509 *x509;
+- FILETIME now;
+- BYTE key_usage[2];
+- DWORD req_size;
+- const unsigned char *encoded_cert;
+-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+- char cert_name[256];
+-#endif
+-
+- pContext = CertEnumCertificatesInStore(hStore, pContext);
+- if(!pContext)
+- break;
+-
+-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+- if(!CertGetNameStringA(pContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
+- NULL, cert_name, sizeof(cert_name))) {
+- strcpy(cert_name, "Unknown");
+- }
+- infof(data, "SSL: Checking cert \"%s\"", cert_name);
+-#endif
+-
+- encoded_cert = (const unsigned char *)pContext->pbCertEncoded;
+- if(!encoded_cert)
+- continue;
+-
+- GetSystemTimeAsFileTime(&now);
+- if(CompareFileTime(&pContext->pCertInfo->NotBefore, &now) > 0 ||
+- CompareFileTime(&now, &pContext->pCertInfo->NotAfter) > 0)
+- continue;
+-
+- /* If key usage exists check for signing attribute */
+- if(CertGetIntendedKeyUsage(pContext->dwCertEncodingType,
+- pContext->pCertInfo,
+- key_usage, sizeof(key_usage))) {
+- if(!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE))
+- continue;
+- }
+- else if(GetLastError())
+- continue;
+-
+- /* If enhanced key usage exists check for server auth attribute.
+- *
+- * Note "In a Microsoft environment, a certificate might also have EKU
+- * extended properties that specify valid uses for the certificate."
+- * The call below checks both, and behavior varies depending on what is
+- * found. For more details see CertGetEnhancedKeyUsage doc.
+- */
+- if(CertGetEnhancedKeyUsage(pContext, 0, NULL, &req_size)) {
+- if(req_size && req_size > enhkey_usage_size) {
+- void *tmp = realloc(enhkey_usage, req_size);
+-
+- if(!tmp) {
+- failf(data, "SSL: Out of memory allocating for OID list");
+- result = CURLE_OUT_OF_MEMORY;
+- break;
+- }
+-
+- enhkey_usage = (CERT_ENHKEY_USAGE *)tmp;
+- enhkey_usage_size = req_size;
+- }
+-
+- if(CertGetEnhancedKeyUsage(pContext, 0, enhkey_usage, &req_size)) {
+- if(!enhkey_usage->cUsageIdentifier) {
+- /* "If GetLastError returns CRYPT_E_NOT_FOUND, the certificate is
+- good for all uses. If it returns zero, the certificate has no
+- valid uses." */
+- if((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND)
+- continue;
+- }
+- else {
+- DWORD i;
+- bool found = false;
+-
+- for(i = 0; i < enhkey_usage->cUsageIdentifier; ++i) {
+- if(!strcmp("1.3.6.1.5.5.7.3.1" /* OID server auth */,
+- enhkey_usage->rgpszUsageIdentifier[i])) {
+- found = true;
+- break;
+- }
+- }
+-
+- if(!found)
+- continue;
+- }
+- }
+- else
+- continue;
+- }
+- else
+- continue;
+-
+- x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded);
+- if(!x509)
+- continue;
+-
+- /* Try to import the certificate. This may fail for legitimate reasons
+- such as duplicate certificate, which is allowed by MS but not
+- OpenSSL. */
+- if(X509_STORE_add_cert(store, x509) == 1) {
+-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+- infof(data, "SSL: Imported cert \"%s\"", cert_name);
+-#endif
+- imported_native_ca = true;
+- }
+- X509_free(x509);
+- }
+-
+- free(enhkey_usage);
+- CertFreeCertificateContext(pContext);
+- CertCloseStore(hStore, 0);
+-
+- if(result)
+- return result;
+- }
+- if(imported_native_ca)
+- infof(data, "successfully imported Windows CA store");
+- else
+- infof(data, "error importing Windows CA store, continuing anyway");
+- }
+-#endif
+-
+- if(ca_info_blob) {
+- result = load_cacert_from_memory(backend->ctx, ca_info_blob);
+- if(result) {
+- if(result == CURLE_OUT_OF_MEMORY ||
+- (verifypeer && !imported_native_ca)) {
+- failf(data, "error importing CA certificate blob");
+- return result;
+- }
+- /* Only warn if no certificate verification is required. */
+- infof(data, "error importing CA certificate blob, continuing anyway");
+- }
+- }
+-
+- if(verifypeer && !imported_native_ca && (ssl_cafile || ssl_capath)) {
+-#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
+- /* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */
+- if(ssl_cafile &&
+- !SSL_CTX_load_verify_file(backend->ctx, ssl_cafile)) {
+- /* Fail if we insist on successfully verifying the server. */
+- failf(data, "error setting certificate file: %s", ssl_cafile);
+- return CURLE_SSL_CACERT_BADFILE;
+- }
+- if(ssl_capath &&
+- !SSL_CTX_load_verify_dir(backend->ctx, ssl_capath)) {
+- /* Fail if we insist on successfully verifying the server. */
+- failf(data, "error setting certificate path: %s", ssl_capath);
+- return CURLE_SSL_CACERT_BADFILE;
+- }
+-#else
+- /* tell OpenSSL where to find CA certificates that are used to verify the
+- server's certificate. */
+- if(!SSL_CTX_load_verify_locations(backend->ctx, ssl_cafile, ssl_capath)) {
+- /* Fail if we insist on successfully verifying the server. */
+- failf(data, "error setting certificate verify locations:"
+- " CAfile: %s CApath: %s",
+- ssl_cafile ? ssl_cafile : "none",
+- ssl_capath ? ssl_capath : "none");
+- return CURLE_SSL_CACERT_BADFILE;
+- }
+-#endif
+- infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
+- infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
+- }
+-
+-#ifdef CURL_CA_FALLBACK
+- if(verifypeer &&
+- !ca_info_blob && !ssl_cafile && !ssl_capath && !imported_native_ca) {
+- /* verifying the peer without any CA certificates won't
+- work so use openssl's built-in default as fallback */
+- SSL_CTX_set_default_verify_paths(backend->ctx);
+- }
+-#endif
+-
+- if(ssl_crlfile) {
+- /* tell OpenSSL where to find CRL file that is used to check certificate
+- * revocation */
+- lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(backend->ctx),
+- X509_LOOKUP_file());
+- if(!lookup ||
+- (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) {
+- failf(data, "error loading CRL file: %s", ssl_crlfile);
+- return CURLE_SSL_CRL_BADFILE;
+- }
+- /* Everything is fine. */
+- infof(data, "successfully loaded CRL file:");
+- X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
+- X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
+-
+- infof(data, " CRLfile: %s", ssl_crlfile);
+- }
+-
+- if(verifypeer) {
+- /* Try building a chain using issuers in the trusted store first to avoid
+- problems with server-sent legacy intermediates. Newer versions of
+- OpenSSL do alternate chain checking by default but we do not know how to
+- determine that in a reliable manner.
+- https://rt.openssl.org/Ticket/Display.html?id=3621&user=guest&pass=guest
+- */
+-#if defined(X509_V_FLAG_TRUSTED_FIRST)
+- X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
+- X509_V_FLAG_TRUSTED_FIRST);
+-#endif
+-#ifdef X509_V_FLAG_PARTIAL_CHAIN
+- if(!SSL_SET_OPTION(no_partialchain) && !ssl_crlfile) {
+- /* Have intermediate certificates in the trust store be treated as
+- trust-anchors, in the same way as self-signed root CA certificates
+- are. This allows users to verify servers using the intermediate cert
+- only, instead of needing the whole chain.
+-
+- Due to OpenSSL bug https://github.com/openssl/openssl/issues/5081 we
+- cannot do partial chains with a CRL check.
+- */
+- X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
+- X509_V_FLAG_PARTIAL_CHAIN);
+- }
+-#endif
+- }
++ result = populate_x509_store(data, conn, sockindex);
++ if(result)
++ return result;
+
+ /* OpenSSL always tries to verify the peer, this only says whether it should
+ * fail to connect if the verification fails, or if it should continue
+--
+2.34.1
+
diff --git a/sdk/recipes/patches/libcurl/0003-openssl-pass-x509-store-to-be-populated.p b/sdk/recipes/patches/libcurl/0003-openssl-pass-x509-store-to-be-populated.p
new file mode 100644
index 0000000..f909bb1
--- /dev/null
+++ b/sdk/recipes/patches/libcurl/0003-openssl-pass-x509-store-to-be-populated.p
@@ -0,0 +1,174 @@
+diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
+index 981075838..d80f79921 100644
+--- lib/vtls/openssl.c
++++ lib/vtls/openssl.c
+@@ -2830,7 +2830,7 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
+ return res;
+ }
+
+-static CURLcode load_cacert_from_memory(SSL_CTX *ctx,
++static CURLcode load_cacert_from_memory(X509_STORE *store,
+ const struct curl_blob *ca_info_blob)
+ {
+ /* these need to be freed at the end */
+@@ -2839,16 +2839,11 @@ static CURLcode load_cacert_from_memory(SSL_CTX *ctx,
+
+ /* everything else is just a reference */
+ int i, count = 0;
+- X509_STORE *cts = NULL;
+ X509_INFO *itmp = NULL;
+
+ if(ca_info_blob->len > (size_t)INT_MAX)
+ return CURLE_SSL_CACERT_BADFILE;
+
+- cts = SSL_CTX_get_cert_store(ctx);
+- if(!cts)
+- return CURLE_OUT_OF_MEMORY;
+-
+ cbio = BIO_new_mem_buf(ca_info_blob->data, (int)ca_info_blob->len);
+ if(!cbio)
+ return CURLE_OUT_OF_MEMORY;
+@@ -2863,7 +2858,7 @@ static CURLcode load_cacert_from_memory(SSL_CTX *ctx,
+ for(i = 0; i < (int)sk_X509_INFO_num(inf); ++i) {
+ itmp = sk_X509_INFO_value(inf, i);
+ if(itmp->x509) {
+- if(X509_STORE_add_cert(cts, itmp->x509)) {
++ if(X509_STORE_add_cert(store, itmp->x509)) {
+ ++count;
+ }
+ else {
+@@ -2873,7 +2868,7 @@ static CURLcode load_cacert_from_memory(SSL_CTX *ctx,
+ }
+ }
+ if(itmp->crl) {
+- if(X509_STORE_add_crl(cts, itmp->crl)) {
++ if(X509_STORE_add_crl(store, itmp->crl)) {
+ ++count;
+ }
+ else {
+@@ -2892,7 +2887,8 @@ static CURLcode load_cacert_from_memory(SSL_CTX *ctx,
+ }
+
+ static CURLcode populate_x509_store(struct Curl_easy *data,
+- struct connectdata *conn, int sockindex)
++ struct connectdata *conn,
++ X509_STORE *store)
+ {
+ CURLcode result = CURLE_OK;
+ X509_LOOKUP *lookup = NULL;
+@@ -2903,10 +2899,11 @@ static CURLcode populate_x509_store(struct Curl_easy *data,
+ const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
+ const char * const ssl_crlfile = SSL_SET_OPTION(primary.CRLfile);
+ const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
+- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+- struct ssl_backend_data *backend = connssl->backend;
+ bool imported_native_ca = false;
+
++ if(!store)
++ return CURLE_OUT_OF_MEMORY;
++
+ #if defined(USE_WIN32_CRYPTO)
+ /* Import certificates from the Windows root certificate store if requested.
+ https://stackoverflow.com/questions/9507184/
+@@ -2914,7 +2911,6 @@ static CURLcode populate_x509_store(struct Curl_easy *data,
+ https://datatracker.ietf.org/doc/html/rfc5280 */
+ if((SSL_CONN_CONFIG(verifypeer) || SSL_CONN_CONFIG(verifyhost)) &&
+ (SSL_SET_OPTION(native_ca_store))) {
+- X509_STORE *store = SSL_CTX_get_cert_store(backend->ctx);
+ HCERTSTORE hStore = CertOpenSystemStore(0, TEXT("ROOT"));
+
+ if(hStore) {
+@@ -3053,7 +3049,7 @@ static CURLcode populate_x509_store(struct Curl_easy *data,
+ #endif
+
+ if(ca_info_blob) {
+- result = load_cacert_from_memory(backend->ctx, ca_info_blob);
++ result = load_cacert_from_memory(store, ca_info_blob);
+ if(result) {
+ if(result == CURLE_OUT_OF_MEMORY ||
+ (verifypeer && !imported_native_ca)) {
+@@ -3069,13 +3065,13 @@ static CURLcode populate_x509_store(struct Curl_easy *data,
+ #if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
+ /* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */
+ if(ssl_cafile &&
+- !SSL_CTX_load_verify_file(backend->ctx, ssl_cafile)) {
++ !X509_STORE_load_file(store, ssl_cafile)) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate file: %s", ssl_cafile);
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ if(ssl_capath &&
+- !SSL_CTX_load_verify_dir(backend->ctx, ssl_capath)) {
++ !X509_STORE_load_path(store, ssl_capath)) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate path: %s", ssl_capath);
+ return CURLE_SSL_CACERT_BADFILE;
+@@ -3083,7 +3079,7 @@ static CURLcode populate_x509_store(struct Curl_easy *data,
+ #else
+ /* tell OpenSSL where to find CA certificates that are used to verify the
+ server's certificate. */
+- if(!SSL_CTX_load_verify_locations(backend->ctx, ssl_cafile, ssl_capath)) {
++ if(!X509_STORE_load_locations(store, ssl_cafile, ssl_capath)) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate verify locations:"
+ " CAfile: %s CApath: %s",
+@@ -3101,15 +3097,14 @@ static CURLcode populate_x509_store(struct Curl_easy *data,
+ !ca_info_blob && !ssl_cafile && !ssl_capath && !imported_native_ca) {
+ /* verifying the peer without any CA certificates won't
+ work so use openssl's built-in default as fallback */
+- SSL_CTX_set_default_verify_paths(backend->ctx);
++ X509_STORE_set_default_paths(store);
+ }
+ #endif
+
+ if(ssl_crlfile) {
+ /* tell OpenSSL where to find CRL file that is used to check certificate
+ * revocation */
+- lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(backend->ctx),
+- X509_LOOKUP_file());
++ lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
+ if(!lookup ||
+ (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) {
+ failf(data, "error loading CRL file: %s", ssl_crlfile);
+@@ -3117,7 +3112,7 @@ static CURLcode populate_x509_store(struct Curl_easy *data,
+ }
+ /* Everything is fine. */
+ infof(data, "successfully loaded CRL file:");
+- X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
++ X509_STORE_set_flags(store,
+ X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
+
+ infof(data, " CRLfile: %s", ssl_crlfile);
+@@ -3131,8 +3126,7 @@ static CURLcode populate_x509_store(struct Curl_easy *data,
+ https://rt.openssl.org/Ticket/Display.html?id=3621&user=guest&pass=guest
+ */
+ #if defined(X509_V_FLAG_TRUSTED_FIRST)
+- X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
+- X509_V_FLAG_TRUSTED_FIRST);
++ X509_STORE_set_flags(store, X509_V_FLAG_TRUSTED_FIRST);
+ #endif
+ #ifdef X509_V_FLAG_PARTIAL_CHAIN
+ if(!SSL_SET_OPTION(no_partialchain) && !ssl_crlfile) {
+@@ -3144,8 +3138,7 @@ static CURLcode populate_x509_store(struct Curl_easy *data,
+ Due to OpenSSL bug https://github.com/openssl/openssl/issues/5081 we
+ cannot do partial chains with a CRL check.
+ */
+- X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
+- X509_V_FLAG_PARTIAL_CHAIN);
++ X509_STORE_set_flags(store, X509_V_FLAG_PARTIAL_CHAIN);
+ }
+ #endif
+ }
+@@ -3450,7 +3443,8 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
+ }
+ #endif
+
+- result = populate_x509_store(data, conn, sockindex);
++ result = populate_x509_store(data, conn,
++ SSL_CTX_get_cert_store(backend->ctx));
+ if(result)
+ return result;
+
+--
+2.34.1
+
diff --git a/sdk/recipes/patches/libcurl/0004-urldata-fix-multi-handle-comment.p b/sdk/recipes/patches/libcurl/0004-urldata-fix-multi-handle-comment.p
new file mode 100644
index 0000000..7bdf402
--- /dev/null
+++ b/sdk/recipes/patches/libcurl/0004-urldata-fix-multi-handle-comment.p
@@ -0,0 +1,16 @@
+diff --git a/lib/urldata.h b/lib/urldata.h
+index f5bd5a3e9..aba07c275 100644
+--- lib/urldata.h
++++ lib/urldata.h
+@@ -1531,7 +1531,7 @@ struct UrlState {
+ * Character pointer fields point to dynamic storage, unless otherwise stated.
+ */
+
+-struct Curl_multi; /* declared and used only in multi.c */
++struct Curl_multi; /* declared in multihandle.c */
+
+ /*
+ * This enumeration MUST not use conditional directives (#ifdefs), new
+--
+2.34.1
+
diff --git a/sdk/recipes/patches/libcurl/0005-multi-vtls-enable-ssl-backend-specific-storage-on-mu.p b/sdk/recipes/patches/libcurl/0005-multi-vtls-enable-ssl-backend-specific-storage-on-mu.p
new file mode 100644
index 0000000..d961322
--- /dev/null
+++ b/sdk/recipes/patches/libcurl/0005-multi-vtls-enable-ssl-backend-specific-storage-on-mu.p
@@ -0,0 +1,245 @@
+diff --git a/lib/multi.c b/lib/multi.c
+index 51acba73a..09965de83 100644
+--- lib/multi.c
++++ lib/multi.c
+@@ -2770,6 +2770,11 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
+ wakeup_close(multi->wakeup_pair[1]);
+ #endif
+ #endif
++
++#ifdef USE_SSL
++ Curl_free_multi_ssl_backend_data(multi->ssl_backend_data);
++#endif
++
+ free(multi);
+
+ return CURLM_OK;
+diff --git a/lib/multihandle.h b/lib/multihandle.h
+index a997784ea..5a83656d5 100644
+--- lib/multihandle.h
++++ lib/multihandle.h
+@@ -79,6 +79,10 @@ typedef enum {
+ /* value for MAXIMUM CONCURRENT STREAMS upper limit */
+ #define INITIAL_MAX_CONCURRENT_STREAMS ((1U << 31) - 1)
+
++/* Curl_multi SSL backend-specific data; declared differently by each SSL
++ backend */
++struct multi_ssl_backend_data;
++
+ /* This is the struct known as CURLM on the outside */
+ struct Curl_multi {
+ /* First a simple identifier to easier detect if a user mix up
+@@ -118,6 +122,10 @@ struct Curl_multi {
+ times of all currently set timers */
+ struct Curl_tree *timetree;
+
++#if defined(USE_SSL)
++ struct multi_ssl_backend_data *ssl_backend_data;
++#endif
++
+ /* 'sockhash' is the lookup hash for socket descriptor => easy handles (note
+ the pluralis form, there can be more than one easy handle waiting on the
+ same actual socket) */
+diff --git a/lib/vtls/bearssl.c b/lib/vtls/bearssl.c
+index 1221ce8c8..e66dd8469 100644
+--- lib/vtls/bearssl.c
++++ lib/vtls/bearssl.c
+@@ -1208,7 +1208,8 @@ const struct Curl_ssl Curl_ssl_bearssl = {
+ Curl_none_false_start, /* false_start */
+ bearssl_sha256sum, /* sha256sum */
+ NULL, /* associate_connection */
+- NULL /* disassociate_connection */
++ NULL, /* disassociate_connection */
++ NULL /* free_multi_ssl_backend_data */
+ };
+
+ #endif /* USE_BEARSSL */
+diff --git a/lib/vtls/gskit.c b/lib/vtls/gskit.c
+index 4ee4edea6..18bd47919 100644
+--- lib/vtls/gskit.c
++++ lib/vtls/gskit.c
+@@ -1323,7 +1323,8 @@ const struct Curl_ssl Curl_ssl_gskit = {
+ Curl_none_false_start, /* false_start */
+ NULL, /* sha256sum */
+ NULL, /* associate_connection */
+- NULL /* disassociate_connection */
++ NULL, /* disassociate_connection */
++ NULL /* free_multi_ssl_backend_data */
+ };
+
+ #endif /* USE_GSKIT */
+diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
+index cf3dbc523..68e3fe299 100644
+--- lib/vtls/gtls.c
++++ lib/vtls/gtls.c
+@@ -1699,7 +1699,8 @@ const struct Curl_ssl Curl_ssl_gnutls = {
+ Curl_none_false_start, /* false_start */
+ gtls_sha256sum, /* sha256sum */
+ NULL, /* associate_connection */
+- NULL /* disassociate_connection */
++ NULL, /* disassociate_connection */
++ NULL /* free_multi_ssl_backend_data */
+ };
+
+ #endif /* USE_GNUTLS */
+diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c
+index fbde8976e..a5250289d 100644
+--- lib/vtls/mbedtls.c
++++ lib/vtls/mbedtls.c
+@@ -1267,7 +1267,8 @@ const struct Curl_ssl Curl_ssl_mbedtls = {
+ Curl_none_false_start, /* false_start */
+ mbedtls_sha256sum, /* sha256sum */
+ NULL, /* associate_connection */
+- NULL /* disassociate_connection */
++ NULL, /* disassociate_connection */
++ NULL /* free_multi_ssl_backend_data */
+ };
+
+ #endif /* USE_MBEDTLS */
+diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
+index b08808c43..55d777d69 100644
+--- lib/vtls/nss.c
++++ lib/vtls/nss.c
+@@ -2530,7 +2530,8 @@ const struct Curl_ssl Curl_ssl_nss = {
+ nss_false_start, /* false_start */
+ nss_sha256sum, /* sha256sum */
+ NULL, /* associate_connection */
+- NULL /* disassociate_connection */
++ NULL, /* disassociate_connection */
++ NULL /* free_multi_ssl_backend_data */
+ };
+
+ #endif /* USE_NSS */
+diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
+index d80f79921..b536b42da 100644
+--- lib/vtls/openssl.c
++++ lib/vtls/openssl.c
+@@ -4619,7 +4619,8 @@ const struct Curl_ssl Curl_ssl_openssl = {
+ NULL, /* sha256sum */
+ #endif
+ ossl_associate_connection, /* associate_connection */
+- ossl_disassociate_connection /* disassociate_connection */
++ ossl_disassociate_connection, /* disassociate_connection */
++ NULL /* free_multi_ssl_backend_data */
+ };
+
+ #endif /* USE_OPENSSL */
+diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c
+index 77a49f1ab..45433bb85 100644
+--- lib/vtls/rustls.c
++++ lib/vtls/rustls.c
+@@ -630,7 +630,8 @@ const struct Curl_ssl Curl_ssl_rustls = {
+ Curl_none_false_start, /* false_start */
+ NULL, /* sha256sum */
+ NULL, /* associate_connection */
+- NULL /* disassociate_connection */
++ NULL, /* disassociate_connection */
++ NULL /* free_multi_ssl_backend_data */
+ };
+
+ #endif /* USE_RUSTLS */
+diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
+index fcfb9c6df..1e6a93106 100644
+--- lib/vtls/schannel.c
++++ lib/vtls/schannel.c
+@@ -2809,7 +2809,8 @@ const struct Curl_ssl Curl_ssl_schannel = {
+ Curl_none_false_start, /* false_start */
+ schannel_sha256sum, /* sha256sum */
+ NULL, /* associate_connection */
+- NULL /* disassociate_connection */
++ NULL, /* disassociate_connection */
++ NULL /* free_multi_ssl_backend_data */
+ };
+
+ #endif /* USE_SCHANNEL */
+diff --git a/lib/vtls/sectransp.c b/lib/vtls/sectransp.c
+index d44f14ba6..d27adedca 100644
+--- lib/vtls/sectransp.c
++++ lib/vtls/sectransp.c
+@@ -3531,7 +3531,8 @@ const struct Curl_ssl Curl_ssl_sectransp = {
+ sectransp_false_start, /* false_start */
+ sectransp_sha256sum, /* sha256sum */
+ NULL, /* associate_connection */
+- NULL /* disassociate_connection */
++ NULL, /* disassociate_connection */
++ NULL /* free_multi_ssl_backend_data */
+ };
+
+ #ifdef __clang__
+diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
+index 9dee5aa3b..8a251b270 100644
+--- lib/vtls/vtls.c
++++ lib/vtls/vtls.c
+@@ -655,6 +655,12 @@ void Curl_ssl_detach_conn(struct Curl_easy *data,
+ }
+ }
+
++void Curl_free_multi_ssl_backend_data(struct multi_ssl_backend_data *mbackend)
++{
++ if(Curl_ssl->free_multi_ssl_backend_data && mbackend)
++ Curl_ssl->free_multi_ssl_backend_data(mbackend);
++}
++
+ void Curl_ssl_close_all(struct Curl_easy *data)
+ {
+ /* kill the session ID cache if not shared */
+@@ -1310,7 +1316,8 @@ static const struct Curl_ssl Curl_ssl_multi = {
+ Curl_none_false_start, /* false_start */
+ NULL, /* sha256sum */
+ NULL, /* associate_connection */
+- NULL /* disassociate_connection */
++ NULL, /* disassociate_connection */
++ NULL /* free_multi_ssl_backend_data */
+ };
+
+ const struct Curl_ssl *Curl_ssl =
+diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h
+index 50c53b3fb..1ab90c09e 100644
+--- lib/vtls/vtls.h
++++ lib/vtls/vtls.h
+@@ -47,6 +47,10 @@ struct ssl_connect_data;
+ #define VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR \
+ ALPN_ACCEPTED "%.*s"
+
++/* Curl_multi SSL backend-specific data; declared differently by each SSL
++ backend */
++struct multi_ssl_backend_data;
++
+ struct Curl_ssl {
+ /*
+ * This *must* be the first entry to allow returning the list of available
+@@ -102,6 +106,8 @@ struct Curl_ssl {
+ struct connectdata *conn,
+ int sockindex);
+ void (*disassociate_connection)(struct Curl_easy *data, int sockindex);
++
++ void (*free_multi_ssl_backend_data)(struct multi_ssl_backend_data *mbackend);
+ };
+
+ #ifdef USE_SSL
+@@ -311,6 +317,8 @@ void Curl_ssl_associate_conn(struct Curl_easy *data,
+ void Curl_ssl_detach_conn(struct Curl_easy *data,
+ struct connectdata *conn);
+
++void Curl_free_multi_ssl_backend_data(struct multi_ssl_backend_data *mbackend);
++
+ #define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */
+
+ #else /* if not USE_SSL */
+diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c
+index 594c39a32..bc2a3c03f 100644
+--- lib/vtls/wolfssl.c
++++ lib/vtls/wolfssl.c
+@@ -1241,7 +1241,8 @@ const struct Curl_ssl Curl_ssl_wolfssl = {
+ Curl_none_false_start, /* false_start */
+ wolfssl_sha256sum, /* sha256sum */
+ NULL, /* associate_connection */
+- NULL /* disassociate_connection */
++ NULL, /* disassociate_connection */
++ NULL /* free_multi_ssl_backend_data */
+ };
+
+ #endif
+--
+2.34.1
+
diff --git a/sdk/recipes/patches/libcurl/0006-openssl-cache-x509-store-on-multi-handle.p b/sdk/recipes/patches/libcurl/0006-openssl-cache-x509-store-on-multi-handle.p
new file mode 100644
index 0000000..da158e6
--- /dev/null
+++ b/sdk/recipes/patches/libcurl/0006-openssl-cache-x509-store-on-multi-handle.p
@@ -0,0 +1,202 @@
+diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
+index b536b42da..6749b4be3 100644
+--- lib/vtls/openssl.c
++++ lib/vtls/openssl.c
+@@ -110,6 +110,10 @@
+ #include <openssl/ui.h>
+ #endif
+
++#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
++#define HAVE_THREADS
++#endif
++
+ #if OPENSSL_VERSION_NUMBER >= 0x00909000L
+ #define SSL_METHOD_QUAL const
+ #else
+@@ -259,6 +263,15 @@
+ #define HAVE_OPENSSL_VERSION
+ #endif
+
++/*
++ * Whether the OpenSSL version has the API needed to support sharing an
++ * X509_STORE between connections. The API is:
++ * * `X509_STORE_up_ref` -- Introduced: OpenSSL 1.1.0.
++ */
++#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* OpenSSL >= 1.1.0 */
++#define HAVE_SSL_X509_STORE_SHARE
++#endif
++
+ struct ssl_backend_data {
+ struct Curl_easy *logger; /* transfer handle to pass trace logs to, only
+ using sockindex 0 */
+@@ -272,6 +285,13 @@ struct ssl_backend_data {
+ #endif
+ };
+
++#if defined(HAVE_SSL_X509_STORE_SHARE)
++struct multi_ssl_backend_data {
++ char *CAfile; /* CAfile path used to generate X509 store */
++ X509_STORE *store; /* cached X509 store or NULL if none */
++};
++#endif /* HAVE_SSL_X509_STORE_SHARE */
++
+ #define push_certinfo(_label, _num) \
+ do { \
+ long info_len = BIO_get_mem_data(mem, &ptr); \
+@@ -3146,6 +3166,113 @@ static CURLcode populate_x509_store(struct Curl_easy *data,
+ return result;
+ }
+
++#if defined(HAVE_SSL_X509_STORE_SHARE)
++static bool cached_x509_store_different(
++ const struct multi_ssl_backend_data *mb,
++ const struct connectdata *conn)
++{
++ if(!mb->CAfile || !SSL_CONN_CONFIG(CAfile))
++ return mb->CAfile != SSL_CONN_CONFIG(CAfile);
++
++ return strcmp(mb->CAfile, SSL_CONN_CONFIG(CAfile));
++}
++
++static X509_STORE *get_cached_x509_store(const struct Curl_easy *data,
++ const struct connectdata *conn)
++{
++ struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi;
++ X509_STORE *store = NULL;
++
++ if(multi &&
++ multi->ssl_backend_data &&
++ multi->ssl_backend_data->store &&
++ !cached_x509_store_different(multi->ssl_backend_data, conn)) {
++ store = multi->ssl_backend_data->store;
++ }
++
++ return store;
++}
++
++static void set_cached_x509_store(const struct Curl_easy *data,
++ const struct connectdata *conn,
++ X509_STORE *store)
++{
++ struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi;
++ struct multi_ssl_backend_data *mbackend;
++
++ if(!multi)
++ return;
++
++ if(!multi->ssl_backend_data) {
++ multi->ssl_backend_data = calloc(1, sizeof(struct multi_ssl_backend_data));
++ if(!multi->ssl_backend_data)
++ return;
++ }
++
++ mbackend = multi->ssl_backend_data;
++
++ if(X509_STORE_up_ref(store)) {
++ char *CAfile = NULL;
++
++ if(SSL_CONN_CONFIG(CAfile)) {
++ CAfile = strdup(SSL_CONN_CONFIG(CAfile));
++ if(!CAfile) {
++ X509_STORE_free(store);
++ return;
++ }
++ }
++
++ if(mbackend->store) {
++ X509_STORE_free(mbackend->store);
++ free(mbackend->CAfile);
++ }
++
++ mbackend->store = store;
++ mbackend->CAfile = CAfile;
++ }
++}
++
++static CURLcode set_up_x509_store(struct Curl_easy *data,
++ struct connectdata *conn,
++ struct ssl_backend_data *backend)
++{
++ CURLcode result = CURLE_OK;
++ X509_STORE *cached_store = get_cached_x509_store(data, conn);
++
++ /* Consider the X509 store cacheable if it comes exclusively from a CAfile,
++ or no source is provided and we are falling back to openssl's built-in
++ default. */
++ bool cache_criteria_met = SSL_CONN_CONFIG(verifypeer) &&
++ !SSL_CONN_CONFIG(CApath) &&
++ !SSL_CONN_CONFIG(ca_info_blob) &&
++ !SSL_SET_OPTION(primary.CRLfile) &&
++ !SSL_SET_OPTION(native_ca_store);
++
++ if(cached_store && cache_criteria_met && X509_STORE_up_ref(cached_store)) {
++ SSL_CTX_set_cert_store(backend->ctx, cached_store);
++ }
++ else {
++ X509_STORE *store = SSL_CTX_get_cert_store(backend->ctx);
++
++ result = populate_x509_store(data, conn, store);
++ if(result == CURLE_OK && cache_criteria_met) {
++ set_cached_x509_store(data, conn, store);
++ }
++ }
++
++ return result;
++}
++#else /* HAVE_SSL_X509_STORE_SHARE */
++static CURLcode set_up_x509_store(struct Curl_easy *data,
++ struct connectdata *conn,
++ struct ssl_backend_data *backend)
++{
++ X509_STORE *store = SSL_CTX_get_cert_store(backend->ctx);
++
++ return populate_x509_store(data, conn, store);
++}
++#endif /* HAVE_SSL_X509_STORE_SHARE */
++
+ static CURLcode ossl_connect_step1(struct Curl_easy *data,
+ struct connectdata *conn, int sockindex)
+ {
+@@ -3443,8 +3570,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
+ }
+ #endif
+
+- result = populate_x509_store(data, conn,
+- SSL_CTX_get_cert_store(backend->ctx));
++ result = set_up_x509_store(data, conn, backend);
+ if(result)
+ return result;
+
+@@ -4579,6 +4705,20 @@ static void ossl_disassociate_connection(struct Curl_easy *data,
+ }
+ }
+
++static void ossl_free_multi_ssl_backend_data(
++ struct multi_ssl_backend_data *mbackend)
++{
++#if defined(HAVE_SSL_X509_STORE_SHARE)
++ if(mbackend->store) {
++ X509_STORE_free(mbackend->store);
++ }
++ free(mbackend->CAfile);
++ free(mbackend);
++#else /* HAVE_SSL_X509_STORE_SHARE */
++ (void)mbackend;
++#endif /* HAVE_SSL_X509_STORE_SHARE */
++}
++
+ const struct Curl_ssl Curl_ssl_openssl = {
+ { CURLSSLBACKEND_OPENSSL, "openssl" }, /* info */
+
+@@ -4620,7 +4760,7 @@ const struct Curl_ssl Curl_ssl_openssl = {
+ #endif
+ ossl_associate_connection, /* associate_connection */
+ ossl_disassociate_connection, /* disassociate_connection */
+- NULL /* free_multi_ssl_backend_data */
++ ossl_free_multi_ssl_backend_data /* free_multi_ssl_backend_data */
+ };
+
+ #endif /* USE_OPENSSL */
+--
+2.34.1
+
diff --git a/sdk/recipes/patches/libcurl/0007-openssl-use-new-x509-store-if-cached-is-24h-old.p b/sdk/recipes/patches/libcurl/0007-openssl-use-new-x509-store-if-cached-is-24h-old.p
new file mode 100644
index 0000000..d9c9c77
--- /dev/null
+++ b/sdk/recipes/patches/libcurl/0007-openssl-use-new-x509-store-if-cached-is-24h-old.p
@@ -0,0 +1,50 @@
+diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
+index 6749b4be3..9c752554e 100644
+--- lib/vtls/openssl.c
++++ lib/vtls/openssl.c
+@@ -287,8 +287,9 @@ struct ssl_backend_data {
+
+ #if defined(HAVE_SSL_X509_STORE_SHARE)
+ struct multi_ssl_backend_data {
+- char *CAfile; /* CAfile path used to generate X509 store */
+- X509_STORE *store; /* cached X509 store or NULL if none */
++ char *CAfile; /* CAfile path used to generate X509 store */
++ X509_STORE *store; /* cached X509 store or NULL if none */
++ struct curltime time; /* when the cached store was created */
+ };
+ #endif /* HAVE_SSL_X509_STORE_SHARE */
+
+@@ -3167,6 +3168,14 @@ static CURLcode populate_x509_store(struct Curl_easy *data,
+ }
+
+ #if defined(HAVE_SSL_X509_STORE_SHARE)
++#define X509_STORE_EXPIRY_MS (24 * 60 * 60 * 1000) /* 24 hours */
++static bool cached_x509_store_expired(const struct multi_ssl_backend_data *mb)
++{
++ struct curltime now = Curl_now();
++
++ return Curl_timediff(now, mb->time) >= X509_STORE_EXPIRY_MS;
++}
++
+ static bool cached_x509_store_different(
+ const struct multi_ssl_backend_data *mb,
+ const struct connectdata *conn)
+@@ -3186,6 +3195,7 @@ static X509_STORE *get_cached_x509_store(const struct Curl_easy *data,
+ if(multi &&
+ multi->ssl_backend_data &&
+ multi->ssl_backend_data->store &&
++ !cached_x509_store_expired(multi->ssl_backend_data) &&
+ !cached_x509_store_different(multi->ssl_backend_data, conn)) {
+ store = multi->ssl_backend_data->store;
+ }
+@@ -3227,6 +3237,7 @@ static void set_cached_x509_store(const struct Curl_easy *data,
+ free(mbackend->CAfile);
+ }
+
++ mbackend->time = Curl_now();
+ mbackend->store = store;
+ mbackend->CAfile = CAfile;
+ }
+--
+2.34.1
+
--
Cross-compilation toolchains and environments
4 months, 3 weeks
toolchains: branch jmb/arm-riscos-gnueabihf updated. 19bad0e13de8b3f09d20efa380cfa2701fed5487
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/toolchains.git/shortlog/19bad0e13de8b3f09d...
...commit http://git.netsurf-browser.org/toolchains.git/commit/19bad0e13de8b3f09d20...
...tree http://git.netsurf-browser.org/toolchains.git/tree/19bad0e13de8b3f09d20ef...
The branch, jmb/arm-riscos-gnueabihf has been updated
discards 6a0e3141ee021b4867a39269c77fe26beb058534 (commit)
discards 0c7fc8e52cefbe787bc5f33dcc9ae95ef3a5247c (commit)
discards 6cdc74a08eda519b862d93ad3cc549a0c055849e (commit)
discards 1853c8c1efc7fd269c853793e79b092160fe4bdd (commit)
discards f5e946d3a4215693381acee1da1ecfc56b2942bc (commit)
discards 7f53178a4cdbed363328a5fa60bead742bd628aa (commit)
discards 98fc44e4b6b635bbf261c03038d470e19a468ba6 (commit)
discards f3df1663ab3e3a102d7903f9ab60b63eb964948e (commit)
discards 108ca67a62fde03373749c6070e0be12784bc567 (commit)
discards 9007b76ef30584fafa8d50c2b25d70a86db6a1b3 (commit)
discards 475c571bf9c7e927cc15688f629b408b69733f5f (commit)
discards 47ba3fab779ff40cdfa1983780f3716d9c20a885 (commit)
discards c60d44f2b9f15efdca4e19f5281091284a54f7e2 (commit)
discards 6525293fc70e3d029e353e88e298c3a3eaef39f1 (commit)
discards 6ca1a847929aec563f8a5f2bad29a741d7dffcfa (commit)
discards dbe6c89fee5c7be5edd3c91eae0ab31dcbf175d7 (commit)
discards 719d796d0dd0cf9af2ebf3fb67dc05a43e6b5f4c (commit)
discards de2c28318fb7406dc6558927e58d6d48adbc5bab (commit)
discards 5e7f8da5116489afbbb7081ec5b06d0c344f73f1 (commit)
discards de12e0342c6e3a037ecd56979525b9174f0e96aa (commit)
discards 00dcdfdff81a236e1019f4fe0cf8d70b7aaed2e7 (commit)
via 19bad0e13de8b3f09d20efa380cfa2701fed5487 (commit)
via 8e3aaa81006331ca878178ea940ea29cca3b7048 (commit)
via 21888fb605067c8729db1a6528925d8bd0bdc549 (commit)
via 96cabae5a4ce327d3cfbecac610a9e7b274cc3b9 (commit)
via f0a188b249f3a07ebc5d0dd7910f39b2752bfd5e (commit)
via 0d13a1b407662de9b820f342d9f11f8e858fe9d7 (commit)
via a6494294026f2e6491bfc6d154b60b4613fa4e8e (commit)
via 30275ec7f1a8b126f884d33103632f1a364387ed (commit)
via 107c1529361b54a0e36388bfa7cba22dfbc1bb03 (commit)
via 8c0e847b1d8df81e7afe8d4c5c6196790e6e3a76 (commit)
via e8d3950da344b454e74e7b6e46a35c18724561ea (commit)
via ae01cbe542362cc99596d4e07c205659200de425 (commit)
via 44e9cb649a93b4f62b3f962e7be31cef00987541 (commit)
via 5614c157989873efdb53cb5633ee9eb461ec814c (commit)
via 702073888df04286767540c3159c2c6e385a761d (commit)
via 2021fafbbafbaa7f8a53ac290b431179c6ec038f (commit)
via 1adf75a71b1a8dde55047f8da8a7ba4e1436d257 (commit)
via 004197f1ecc4f9636ee579daa2a5566faba240b4 (commit)
via c428f82587d0c284aa0217ffdece91808fc292e9 (commit)
via d97b2bb44b20de3a689a88005b24c1102a243b27 (commit)
via 8dda0314c78da253226ee3f3c6bae57b4b52068a (commit)
via 2bbddd7aaabeae11c1862787ef6f99b3b816324a (commit)
via db19136aaabca03642d4d79facf70e567a3c2536 (commit)
This update added new revisions after undoing existing revisions. That is
to say, the old revision is not a strict subset of the new revision. This
situation occurs when you --force push a change and generate a repository
containing something like this:
* -- * -- B -- O -- O -- O (6a0e3141ee021b4867a39269c77fe26beb058534)
\
N -- N -- N (19bad0e13de8b3f09d20efa380cfa2701fed5487)
When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=19bad0e13de8b3f0...
commit 19bad0e13de8b3f09d20efa380cfa2701fed5487
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
SDK/arm-unknown-riscos: poke function names
diff --git a/sdk/Makefile b/sdk/Makefile
index 9146367..a8dda57 100644
--- a/sdk/Makefile
+++ b/sdk/Makefile
@@ -77,6 +77,10 @@ pkg_config_libdir__ := $(GCCSDK_INSTALL_ENV)/lib/pkgconfig
# Target
TARGET := $(shell $(cc__) -dumpmachine)
+ifeq ($(findstring -riscos,$(TARGET)),-riscos)
+ cflags__ := $(cflags__) -mpoke-function-name
+endif
+
# Environment
# Newer autotools objects to -I appearing in CFLAGS
cleanenv := PATH="$(path__)" CC="$(cc__)" CXX="$(cxx__)" AR="$(ar__)" RANLIB="$(ranlib__)" CPPFLAGS="$(cppflags__)" LDFLAGS="$(ldflags__)" PKG_CONFIG_LIBDIR="$(pkg_config_libdir__)"
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=8e3aaa81006331ca...
commit 8e3aaa81006331ca878178ea940ea29cca3b7048
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Fix unixlib-stdtime.p
Previous attempt contained unrelated detritus already present in
posix-extended-locale.p
diff --git a/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-stdtime.p b/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-stdtime.p
index fcdc7f3..3ad890a 100644
--- a/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-stdtime.p
+++ b/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-stdtime.p
@@ -15,12 +15,3 @@ Index: libunixlib/time/stdtime.c
: "r" (territory), "r" (ro_time), "r" (buf), "r" (size), "r" (str),
[SWI_Territory_ConvertDateAndTime] "i" (Territory_ConvertDateAndTime | (1<<17))
: "r14", "cc", "memory");
-@@ -48,7 +50,7 @@
- #ifdef __TARGET_SCL__
- -1,
- #else
-- __locale_territory[LC_TIME],
-+ __locale_global.locale_territory[LC_TIME],
- #endif
- riscos_time,
- result,
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=21888fb605067c87...
commit 21888fb605067c8729db1a6528925d8bd0bdc549
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Fix __standard_time()
Territory_ConvertDateAndTime modifies r0-r3. Previously, UnixLib
was only telling the compiler that r0 and r1 were modified. This
resulted in the register allocator assuming that the value of r2
on exit was the same as it was on entry and thus returning a
completely garbage value as the result of __standard_time().
Resolve this by telling the compiler the full facts.
diff --git a/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-stdtime.p b/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-stdtime.p
new file mode 100644
index 0000000..fcdc7f3
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-stdtime.p
@@ -0,0 +1,26 @@
+Index: libunixlib/time/stdtime.c
+===================================================================
+--- libunixlib/time/stdtime.c (revision 7698)
++++ libunixlib/time/stdtime.c (working copy)
+@@ -23,9 +23,11 @@
+ register const char *str __asm ("r4") = __str;
+ register const _kernel_oserror *err __asm ("r0");
+ register char *term __asm ("r1");
++ register size_t left __asm ("r2");
++ register const char *ostr __asm ("r3");
+ __asm__ volatile ("SWI\t%[SWI_Territory_ConvertDateAndTime]\n\t"
+ "MOVVC\tr0, #0\n\t"
+- : "=r" (err), "=r" (term)
++ : "=r" (err), "=r" (term), "=r" (left), "=r" (ostr)
+ : "r" (territory), "r" (ro_time), "r" (buf), "r" (size), "r" (str),
+ [SWI_Territory_ConvertDateAndTime] "i" (Territory_ConvertDateAndTime | (1<<17))
+ : "r14", "cc", "memory");
+@@ -48,7 +50,7 @@
+ #ifdef __TARGET_SCL__
+ -1,
+ #else
+- __locale_territory[LC_TIME],
++ __locale_global.locale_territory[LC_TIME],
+ #endif
+ riscos_time,
+ result,
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=96cabae5a4ce327d...
commit 96cabae5a4ce327d3cfbecac610a9e7b274cc3b9
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Use UnixLib's atomics implementation
Stop libgcc pulling in the atomics implementation for Linux. This
does not work on RISC OS and will result in unexpected aborts
deep in application code.
Additionally, enable the __sync_fetch_and_<op>_<size> atomics
when building UnixLib for EABI. It's not clear why these were
disabled, but things that need them will fail to link if they
are not present.
diff --git a/arm-riscos-gnueabihf/recipes/patches/gccsdk/gcc-libgcc-no-linux-atomics.p b/arm-riscos-gnueabihf/recipes/patches/gccsdk/gcc-libgcc-no-linux-atomics.p
new file mode 100644
index 0000000..12a88ac
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/patches/gccsdk/gcc-libgcc-no-linux-atomics.p
@@ -0,0 +1,56 @@
+Index: gcc/libgcc.config.arm.t-riscos-gnueabihf
+===================================================================
+--- gcc/libgcc.config.arm.t-riscos-gnueabihf (revision 7698)
++++ gcc/libgcc.config.arm.t-riscos-gnueabihf (working copy)
+@@ -1,36 +1,2 @@
+-# Copyright (C) 2011-2012 Free Software Foundation, Inc.
+-# Contributed by John Tytgat (John.Tytgat(a)aaug.net).
+-#
+-# This file is part of GCC.
+-#
+-# GCC 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 3, or (at your option)
+-# any later version.
+-#
+-# GCC 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 GCC; see the file COPYING3. If not see
+-# <http://www.gnu.org/licenses/>.
+-
+-# vvv Part of config/arm/t-bpabi
+-LIB2ADD_ST += $(srcdir)/config/arm/fp16.c
+-
+-LIB2ADDEH = $(srcdir)/config/arm/unwind-arm.c \
+- $(srcdir)/config/arm/libunwind.S \
+- $(srcdir)/config/arm/pr-support.c $(srcdir)/unwind-c.c
+-# ^^^
+-
+-ifeq (,$(findstring mlibscl,$(CFLAGS))$(findstring mmodule,$(CFLAGS)))
+-# For shared libgcc building:
+-EXTRA_PARTS += crtbeginS.o crtendS.o
+-gcc_s_compile += -fPIC
+-SHLIB_LDFLAGS=-fPIC
+-include $(srcdir)/config/t-slibgcc
+-include $(srcdir)/config/t-slibgcc-nolc-override
+-endif
+-
++# Use a version of div0 which raises SIGFPE, and a special __clear_cache.
++LIB1ASMFUNCS := $(filter-out _dvmd_tls,$(LIB1ASMFUNCS)) _dvmd_lnx _clear_cache
+Index: gcc/libgcc.config.host.p
+===================================================================
+--- gcc/libgcc.config.host.p (revision 7698)
++++ gcc/libgcc.config.host.p (working copy)
+@@ -20,7 +20,7 @@
+ ;;
+ +arm*-riscos-gnueabihf)
+ + tmake_file="${tmake_file} arm/t-arm t-fixedpoint-gnu-prefix t-crtfm"
+-+ tmake_file="${tmake_file} arm/t-elf arm/t-bpabi arm/t-linux-eabi t-slibgcc-libgcc t-slibgcc-nolc-override"
+++ tmake_file="${tmake_file} arm/t-elf arm/t-bpabi arm/t-riscos-gnueabihf t-slibgcc-libgcc t-slibgcc-nolc-override"
+ + tm_file="$tm_file arm/bpabi-lib.h"
+ + unwind_header=config/arm/unwind-arm.h
+ + tmake_file="$tmake_file t-softfp-sfdf t-softfp-excl arm/t-softfp t-softfp"
diff --git a/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-sync-and-fetch-atomics.p b/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-sync-and-fetch-atomics.p
new file mode 100644
index 0000000..f9764ba
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-sync-and-fetch-atomics.p
@@ -0,0 +1,22 @@
+Index: libunixlib/gcccompat/atomics.c
+===================================================================
+--- libunixlib/gcccompat/atomics.c (revision 7698)
++++ libunixlib/gcccompat/atomics.c (working copy)
+@@ -146,8 +146,6 @@
+ ATOMIC_COMPARE_AND_EXCHANGE(4,uint32_t)
+ ATOMIC_COMPARE_AND_EXCHANGE(8,uint64_t)
+
+-#ifndef __ARM_EABI__
+-
+ /* These built-in functions perform the operation suggested by the name,
+ * and return the value that had previously been in *ptr. That is,
+ *
+@@ -200,8 +198,6 @@
+ SYNC_FETCH_AND_OP(xor,^,8,long long)
+ SYNC_FETCH_AND_OP(and,&,8,long long)
+
+-#endif
+-
+ /* These built-in functions perform the operation suggested by the name,
+ * and return the new value. That is,
+ *
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=f0a188b249f3a07e...
commit f0a188b249f3a07ebc5d0dd7910f39b2752bfd5e
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Revert "Fix stack backtraces from UnixLib"
This reverts commit 7f53178a4cdbed363328a5fa60bead742bd628aa.
It turns out that the situation with stack frames in the EABI
toolchain is currently completely inconsistent. Some functions
end up with APCS-32 stack frames, others with AAPCS frames. It
is not reliably possible to distinguish which is which when
unwinding the stack to generate a backtrace. It also means that
the signal stack frame created in _signal.s would need to reflect
whatever reality made sense for the function that aborted.
Give up.
diff --git a/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-backtrace.p b/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-backtrace.p
deleted file mode 100644
index 2c971cd..0000000
--- a/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-backtrace.p
+++ /dev/null
@@ -1,37 +0,0 @@
---- libunixlib/signal/post.c 2021-06-15 21:42:03.000000000 +0100
-+++ libunixlib/signal/post.c 2022-06-03 19:52:18.316234729 +0100
-@@ -307,6 +307,7 @@
- }
-
- #ifdef __ARM_EABI__
-+ const unsigned int *pc = NULL;
- const unsigned int * const lr = (unsigned int *)fp[LR_OFFSET];
- fprintf (stderr, " (%8x) lr: %8x",
- (unsigned int)fp, (unsigned int)lr);
-@@ -350,7 +351,6 @@
- #endif
- oldfp = fp;
- fp = (const unsigned int *)fp[FP_OFFSET];
--#ifndef __ARM_EABI__
- if (__ul_callbackfp != NULL && fp == __ul_callbackfp)
- {
- /* At &oldfp[1] = cpsr, a1-a4, v1-v6, sl, fp, ip, sp, lr, pc */
-@@ -424,7 +424,6 @@
-
- fputs ("\n\n", stderr);
- }
--#endif
- }
-
- fputc ('\n', stderr);
---- libunixlib/signal/_signal.s 2020-05-31 20:11:06.000000000 +0100
-+++ libunixlib/signal/_signal.s 2022-06-03 19:45:32.872892834 +0100
-@@ -761,7 +761,7 @@
- LDR a3, [sp, #14*4 + 4] @ saved USR lr
- LDR a1, [sp, #11*4 + 4] @ saved USR fp
- STMFD sp!, {a1, a3} @ create signal frame
-- MOV fp, sp @ FIXME: check this with compiler output for similar function
-+ ADD fp, sp, #4 @ FIXME: check this with compiler output for similar function
- #else
- @ Create an APCS-32 compilant signal stack frame
- ADR a4, __h_cback + 4*3 @ point at handler name for backtrace
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=0d13a1b407662de9...
commit 0d13a1b407662de9b820f342d9f11f8e858fe9d7
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Fix stack backtraces from UnixLib
The frame pointer to the signal stack frame was off-by-one
resulting in unwinding terminating early. Additionally, we can
dump the register state at the point of the abort now.
diff --git a/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-backtrace.p b/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-backtrace.p
new file mode 100644
index 0000000..2c971cd
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-backtrace.p
@@ -0,0 +1,37 @@
+--- libunixlib/signal/post.c 2021-06-15 21:42:03.000000000 +0100
++++ libunixlib/signal/post.c 2022-06-03 19:52:18.316234729 +0100
+@@ -307,6 +307,7 @@
+ }
+
+ #ifdef __ARM_EABI__
++ const unsigned int *pc = NULL;
+ const unsigned int * const lr = (unsigned int *)fp[LR_OFFSET];
+ fprintf (stderr, " (%8x) lr: %8x",
+ (unsigned int)fp, (unsigned int)lr);
+@@ -350,7 +351,6 @@
+ #endif
+ oldfp = fp;
+ fp = (const unsigned int *)fp[FP_OFFSET];
+-#ifndef __ARM_EABI__
+ if (__ul_callbackfp != NULL && fp == __ul_callbackfp)
+ {
+ /* At &oldfp[1] = cpsr, a1-a4, v1-v6, sl, fp, ip, sp, lr, pc */
+@@ -424,7 +424,6 @@
+
+ fputs ("\n\n", stderr);
+ }
+-#endif
+ }
+
+ fputc ('\n', stderr);
+--- libunixlib/signal/_signal.s 2020-05-31 20:11:06.000000000 +0100
++++ libunixlib/signal/_signal.s 2022-06-03 19:45:32.872892834 +0100
+@@ -761,7 +761,7 @@
+ LDR a3, [sp, #14*4 + 4] @ saved USR lr
+ LDR a1, [sp, #11*4 + 4] @ saved USR fp
+ STMFD sp!, {a1, a3} @ create signal frame
+- MOV fp, sp @ FIXME: check this with compiler output for similar function
++ ADD fp, sp, #4 @ FIXME: check this with compiler output for similar function
+ #else
+ @ Create an APCS-32 compilant signal stack frame
+ ADR a4, __h_cback + 4*3 @ point at handler name for backtrace
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=a6494294026f2e64...
commit a6494294026f2e6491bfc6d154b60b4613fa4e8e
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Teach elf2aif to handle EABI binaries
The previous attempt was bogus as elf2aif is built for the system
that the cross compiler runs on and thus __ARM_EABI__ would only
be set if the cross compiler was built for an ARM-based system.
Further, removing the OSABI check completely is fragile, so let's
not do that.
Instead, we introduce a new command line option for elf2aif which
must be specified if processing EABI binaries. This alters the
OSABI check to test for SysV, rather than ARM in the EABI case.
Additionally, correct functioning of ARMEABISupport is reliant on
the application loader to cause the ARMEABISupport abort handler
to be installed. For ELF binaries, this is ensured by SOManager.
For AIF binaries, however, RISC OS itself knows nothing about
ARMEABISupport and thus will not ensure that the abort handler
is installed. Make elf2aif inject the necessary SWI call into
_start (overwriting instructions that are meaningless when the
binary is not loaded by SOManager). This ensures that the abort
handler is installed as early in the application execution as
possible (and long before any memory managed by ARMEABISupport
is allocated).
diff --git a/arm-riscos-gnueabihf/recipes/patches/gccsdk/elf2aif-eabi-support.p b/arm-riscos-gnueabihf/recipes/patches/gccsdk/elf2aif-eabi-support.p
new file mode 100644
index 0000000..1d8b841
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/patches/gccsdk/elf2aif-eabi-support.p
@@ -0,0 +1,110 @@
+Index: elf2aif/src/elf2aif.c
+===================================================================
+--- elf2aif/src/elf2aif.c (revision 7698)
++++ elf2aif/src/elf2aif.c (working copy)
+@@ -72,12 +72,13 @@
+ } aifheader_t;
+
+ static int opt_verbose = 0;
++static int opt_eabi = 0;
+
+ static Elf32_External_Ehdr elf_ehdr;
+ static phdr_list_t *elf_phdrlistP;
+ static const char *elf_filename;
+
+-static const unsigned int aifcode[] = {
++static const uint32_t aifcode[] = {
+ 0xE1A00000, /* NOP (BL decompress) */
+ 0xE1A00000, /* NOP (BL self-relocate) */
+ 0xEB00000C, /* BL zero-init */
+@@ -113,6 +114,24 @@
+ 0xEAFFFFFB /* B zeroloop */
+ };
+
++static const uint32_t crt0code[] = {
++ 0xE59F3010, /* LDR R3, =crt1_data */
++ 0xE583000C, /* STR R0, [R3, #12] */
++ 0xE583101C, /* STR R1, [R3, #28] */
++ 0xE5832020, /* STR R2, [R3, #32] */
++ 0xE1A00003 /* MOV R0, R3 */
++ /* B __main */
++};
++
++static const uint32_t eabi_crt0code[] = {
++ 0xE59F3010, /* LDR R3, =crt1_data */
++ 0xE583000C, /* STR R0, [R3, #12] */
++ 0xE3A00002, /* MOV R0, #2 */
++ 0xEF059D01, /* SWI ARMEABISupport_AbortOp */
++ 0xE1A00003 /* MOV R0, R3 */
++ /* B __main */
++};
++
+ /* Read a little-endian 'short' value. */
+ static uint16_t
+ RdShort (const uint8_t sh[2])
+@@ -143,6 +162,7 @@
+ fprintf (stderr, "Usage: elf2aif [options] <ELF file> [<AIF file>]\n"
+ "Convert static ARM ELF binary to AIF (Acorn Image Format) binary.\n"
+ "Options:\n"
++ " -e, --eabi source binary uses EABI\n"
+ " -v, --verbose prints informational messages during processing\n"
+ " --help display this help and exit\n"
+ " --version output version information and exit\n");
+@@ -201,7 +221,8 @@
+ return EXIT_FAILURE;
+ }
+
+- if (elf_ehdr.e_ident[EI_OSABI] != ELFOSABI_ARM)
++ if ((!opt_eabi && elf_ehdr.e_ident[EI_OSABI] != ELFOSABI_ARM) ||
++ (opt_eabi && elf_ehdr.e_ident[EI_OSABI] != ELFOSABI_NONE))
+ {
+ fprintf (stderr, "ELF file '%s' is not for ARM\n", elf_filename);
+ return EXIT_FAILURE;
+@@ -503,6 +524,37 @@
+ return EXIT_FAILURE;
+ }
+
++ /* In the EABI case we need to inject the code to install
++ * the ARMEABISupport abort handler */
++ if (opt_eabi)
++ {
++ uint32_t crt0[5];
++ assert(sizeof (crt0code) == sizeof (crt0));
++ assert(sizeof (eabi_crt0code) == sizeof (crt0));
++
++ if (opt_verbose)
++ printf ("Rewriting crt0 at offset 0x%x\n", (exec_addr - load_addr));
++
++ if (fseek (elfhandle, (exec_addr - load_addr), SEEK_SET) != 0 ||
++ fread (crt0, sizeof (crt0), 1, elfhandle) != 1)
++ {
++ fprintf (stderr, "Failed to read crt0\n");
++ return EXIT_FAILURE;
++ }
++ if (memcmp(crt0, crt0code, sizeof (crt0)) != 0)
++ {
++ fprintf (stderr, "crt0 code not as expected\n");
++ return EXIT_FAILURE;
++ }
++ if (fseek (aifhandle, (exec_addr - load_addr), SEEK_SET) != 0 ||
++ fwrite (eabi_crt0code, sizeof (crt0), 1, aifhandle) != 1 ||
++ fseek (aifhandle, aifend, SEEK_SET) != 0)
++ {
++ fprintf (stderr, "Failed to write crt0\n");
++ return EXIT_FAILURE;
++ }
++ }
++
+ return EXIT_SUCCESS;
+ }
+
+@@ -683,6 +735,9 @@
+ fprintf (stderr, "Warning: extra options/arguments ignored\n");
+ return EXIT_SUCCESS;
+ }
++ else if (!strcmp (&argv[i][1], "-eabi")
++ || !strcmp (&argv[i][1], "e"))
++ opt_eabi = 1;
+ else if (!strcmp (&argv[i][1], "-verbose")
+ || !strcmp (&argv[i][1], "v"))
+ ++opt_verbose;
diff --git a/arm-riscos-gnueabihf/recipes/patches/gccsdk/elf2aif-no-abi-check.p b/arm-riscos-gnueabihf/recipes/patches/gccsdk/elf2aif-no-abi-check.p
deleted file mode 100644
index 3ad6372..0000000
--- a/arm-riscos-gnueabihf/recipes/patches/gccsdk/elf2aif-no-abi-check.p
+++ /dev/null
@@ -1,16 +0,0 @@
-Index: elf2aif/src/elf2aif.c
-===================================================================
---- elf2aif/src/elf2aif.c (revision 7698)
-+++ elf2aif/src/elf2aif.c (working copy)
-@@ -201,7 +201,11 @@
- return EXIT_FAILURE;
- }
-
-+#ifndef __ARM_EABI__
- if (elf_ehdr.e_ident[EI_OSABI] != ELFOSABI_ARM)
-+#else
-+ if (elf_ehdr.e_ident[EI_OSABI] != ELFOSABI_NONE)
-+#endif
- {
- fprintf (stderr, "ELF file '%s' is not for ARM\n", elf_filename);
- return EXIT_FAILURE;
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=30275ec7f1a8b126...
commit 30275ec7f1a8b126f884d33103632f1a364387ed
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
SDK build runes for arm-riscos-gnueabihf
Follows the existing arm-unknown-riscos setup.
diff --git a/sdk/Makefile b/sdk/Makefile
index 1cc3418..9146367 100644
--- a/sdk/Makefile
+++ b/sdk/Makefile
@@ -7,6 +7,7 @@
# GCCSDK_INSTALL_CROSSBIN -- /path/to/toolchain/bin
#
# supported targets are:
+# arm-riscos-gnueabihf
# arm-unknown-riscos
# m68k-atari-mint
# m5475-atari-mint
@@ -116,6 +117,13 @@ FREETYPE_ENV := LIBPNG_CFLAGS=$$($(GCCSDK_INSTALL_ENV)/bin/libpng-config --cflag
LIBJPEG_TURBO_BUILDDIR:=$(BUILDDIR)/libjpegturbo
# Target Specific setup
+ifeq ($(TARGET),arm-riscos-gnueabihf)
+ SDK_ITEMS := $(addprefix $(BUILDSTEPS)/, $(COMMON_SDK_ITEMS) libjpeg-turbo.d libwebp.d)
+ EXTRAARGS_LIBCARES := --disable-shared
+ EXTRAARGS_LIBCURL := --enable-nonblocking --enable-ares --with-random="/dev/urandom" $(LIBCURL_DISABLES)
+ EXTRAARGS_OPENSSL := no-asm
+endif
+
ifeq ($(TARGET),arm-unknown-riscos)
SDK_ITEMS := $(addprefix $(BUILDSTEPS)/, $(COMMON_SDK_ITEMS) libjpeg-turbo.d libwebp.d)
EXTRAARGS_LIBCARES := --disable-shared
diff --git a/sdk/recipes/patches/openssl/Configurations-50-riscos.conf.p b/sdk/recipes/patches/openssl/Configurations-50-riscos.conf.p
index c05a4ad..f3d4dc1 100644
--- a/sdk/recipes/patches/openssl/Configurations-50-riscos.conf.p
+++ b/sdk/recipes/patches/openssl/Configurations-50-riscos.conf.p
@@ -1,6 +1,6 @@
--- /dev/null 2017-10-10 15:19:45.611896396 +0100
+++ Configurations/50-riscos.conf 2017-10-17 15:42:25.304921197 +0100
-@@ -0,0 +1,14 @@
+@@ -0,0 +1,26 @@
+my %targets = (
+
+ "arm-unknown-riscos" => {
@@ -14,4 +14,16 @@
+ sys_id => "RISCOS",
+ bn_ops => "BN_LLONG",
+ },
++
++ "arm-riscos-gnueabihf" => {
++ inherit_from => [ "BASE_unix" ],
++ cc => "arm-riscos-gnueabihf-gcc",
++ cflags => picker(default => "-DL_ENDIAN -DTERMIOS -DNO_SYS_UN_H",
++ debug => "-O0 -g",
++ release => "-O3 ",
++ threads("-D_REENTRANT")),
++ thread_scheme => "(unknown)",
++ sys_id => "RISCOS",
++ bn_ops => "BN_LLONG",
++ },
+);
diff --git a/sdk/recipes/patches/openssl/Configure.p b/sdk/recipes/patches/openssl/Configure.p
index 6b1a39e..f44d99d 100644
--- a/sdk/recipes/patches/openssl/Configure.p
+++ b/sdk/recipes/patches/openssl/Configure.p
@@ -1,9 +1,10 @@
--- Configure.orig 2017-10-17 14:53:18.369801491 +0100
+++ Configure 2017-10-17 15:11:04.312242542 +0100
-@@ -1329,6 +1329,7 @@
+@@ -1329,6 +1329,8 @@
$target{cxxflags}//=$target{cflags} if $target{CXX};
$target{exe_extension}=".exe" if ($config{target} eq "DJGPP");
$target{exe_extension}=".pm" if ($config{target} =~ /vos/);
++$target{exe_extension}=",e1f" if ($config{target} eq "arm-riscos-gnueabihf");
+$target{exe_extension}=",e1f" if ($config{target} eq "arm-unknown-riscos");
# Fill %config with values from %user, and in case those are undefined or
diff --git a/sdk/recipes/patches/zlib/arm-riscos-gnueabihf/configure.p b/sdk/recipes/patches/zlib/arm-riscos-gnueabihf/configure.p
new file mode 100644
index 0000000..24d7a7e
--- /dev/null
+++ b/sdk/recipes/patches/zlib/arm-riscos-gnueabihf/configure.p
@@ -0,0 +1,42 @@
+--- configure.orig 2012-05-02 05:17:08.000000000 +0100
++++ configure 2012-07-17 17:57:01.000000000 +0100
+@@ -423,18 +423,18 @@
+ echo >> configure.log
+
+ # check for large file support, and if none, check for fseeko()
+-cat > $test.c <<EOF
+-#include <sys/types.h>
+-off64_t dummy = 0;
+-EOF
+-if try $CC -c $CFLAGS -D_LARGEFILE64_SOURCE=1 $test.c; then
+- CFLAGS="${CFLAGS} -D_LARGEFILE64_SOURCE=1"
+- SFLAGS="${SFLAGS} -D_LARGEFILE64_SOURCE=1"
+- ALL="${ALL} all64"
+- TEST="${TEST} test64"
+- echo "Checking for off64_t... Yes." | tee -a configure.log
+- echo "Checking for fseeko... Yes." | tee -a configure.log
+-else
++#cat > $test.c <<EOF
++##include <sys/types.h>
++#off64_t dummy = 0;
++#EOF
++#if try $CC -c $CFLAGS -D_LARGEFILE64_SOURCE=1 $test.c; then
++# CFLAGS="${CFLAGS} -D_LARGEFILE64_SOURCE=1"
++# SFLAGS="${SFLAGS} -D_LARGEFILE64_SOURCE=1"
++# ALL="${ALL} all64"
++# TEST="${TEST} test64"
++# echo "Checking for off64_t... Yes." | tee -a configure.log
++# echo "Checking for fseeko... Yes." | tee -a configure.log
++#else
+ echo "Checking for off64_t... No." | tee -a configure.log
+ echo >> configure.log
+ cat > $test.c <<EOF
+@@ -451,7 +451,7 @@
+ SFLAGS="${SFLAGS} -DNO_FSEEKO"
+ echo "Checking for fseeko... No." | tee -a configure.log
+ fi
+-fi
++##fi
+
+ echo >> configure.log
+
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=107c1529361b54a0...
commit 107c1529361b54a0e36388bfa7cba22dfbc1bb03
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Make ro-install available
The OSLib buildsystem expects this to exist, so ensure it does,
patching the original to find the correct objdump binary.
diff --git a/arm-riscos-gnueabihf/Makefile b/arm-riscos-gnueabihf/Makefile
index 6c53c9b..1deec0f 100644
--- a/arm-riscos-gnueabihf/Makefile
+++ b/arm-riscos-gnueabihf/Makefile
@@ -3,6 +3,7 @@ UPSTREAM_GCCSDK_VERSION := 7698
UPSTREAM_GCCSDK_TARBALL := gccsdk$(UPSTREAM_GCCSDK_VERSION).tar.gz
UPSTREAM_GCCSDK_URI := svn://svn.riscos.info/gccsdk/trunk/autobuilder/develop/gcc@$(UPSTREAM_GCCSDK_VERSION)
UPSTREAM_GCCSDK_SGP_URI := svn://svn.riscos.info/gccsdk/trunk/gcc4/setup-gccsdk-params@$(UPSTREAM_GCCSDK_VERSION)
+UPSTREAM_GCCSDK_ROINSTALL_URI := svn://svn.riscos.info/gccsdk/trunk/gcc4/porting-scripts/ro-install@$(UPSTREAM_GCCSDK_VERSION)
UPSTREAM_GCCSDK_AMP_URI := svn://svn.riscos.info/gccsdk/trunk/gcc4/recipe/patches/automake-for-binutils@$(UPSTREAM_GCCSDK_VERSION)
UPSTREAM_GCCSDK_UNIXLIB_URI := svn://svn.riscos.info/gccsdk/trunk/gcc4/recipe/files/gcc/libunixlib@$(UPSTREAM_GCCSDK_VERSION)
UPSTREAM_GCCSDK_LD_URI := svn://svn.riscos.info/gccsdk/trunk/gcc4/riscos/soloader/dynamic/ld.so-1.9.9@$(UPSTREAM_GCCSDK_VERSION)
@@ -124,6 +125,10 @@ $(BUILDSTEPS)/oslib.d: $(BUILDSTEPS)/gcc.d $(SOURCESDIR)/$(UPSTREAM_OSLIB_TARBAL
$(BUILDSTEPS)/gcc.d: $(BUILDSTEPS)/gccsdk-srcdir.d
cd $(BUILDDIR)/gccsdk && make
+ @# Install ro-install
+ mkdir -p $(PREFIX)/env
+ sed -e s:GCCSDK_ENV:$(PREFIX)/env:g < $(BUILDDIR)/gccsdk/ro-install > $(PREFIX)/env/ro-install
+ chmod 755 $(PREFIX)/env/ro-install
@# Install empty libraries needed to fool configure scripts
for l in c pthread gcc_s ; do $(PREFIX)/cross/bin/$(TARGET_NAME)-ar mv $(PREFIX)/cross/$(TARGET_NAME)/lib/lib$$l.a ; done
@# Newer GCCSDK adds these trampoline binaries that for us
@@ -152,6 +157,7 @@ $(BUILDSTEPS)/gccsdk-srcdir.d: $(BUILDSTEPS)/buildsteps.d $(SOURCESDIR)/$(UPSTRE
$(SOURCESDIR)/$(UPSTREAM_GCCSDK_TARBALL):
svn export $(UPSTREAM_GCCSDK_URI) $(SOURCESDIR)/gccsdk/gcc
svn export $(UPSTREAM_GCCSDK_SGP_URI) $(SOURCESDIR)/gccsdk/
+ svn export $(UPSTREAM_GCCSDK_ROINSTALL_URI) $(SOURCESDIR)/gccsdk/
svn export $(UPSTREAM_GCCSDK_AMP_URI) $(SOURCESDIR)/gccsdk/automake
svn export $(UPSTREAM_GCCSDK_UNIXLIB_URI) $(SOURCESDIR)/gccsdk/libunixlib
svn export $(UPSTREAM_GCCSDK_LD_URI) $(SOURCESDIR)/gccsdk/ld
diff --git a/arm-riscos-gnueabihf/recipes/patches/gccsdk/roinstall-objdump-name.p b/arm-riscos-gnueabihf/recipes/patches/gccsdk/roinstall-objdump-name.p
new file mode 100644
index 0000000..7451829
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/patches/gccsdk/roinstall-objdump-name.p
@@ -0,0 +1,13 @@
+Index: ro-install
+===================================================================
+--- ro-install (revision 7698)
++++ ro-install (working copy)
+@@ -72,7 +72,7 @@
+
+ # Check that static libraries really do contain static objects
+ if grep -q "\.a\$" <<< $param || grep -q "\.a-static" <<< $param ; then
+- if GCCSDK_BIN/arm-unknown-riscos-objdump -p $param | grep -q "position independent"; then
++ if GCCSDK_BIN/arm-riscos-gnueabihf-objdump -p $param | grep -q "position independent"; then
+ echo "RISC OS Cross installer: static archive $param contains position independent code" 1>&2
+ exit 1
+ fi
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=8c0e847b1d8df81e...
commit 8c0e847b1d8df81e7afe8d4c5c6196790e6e3a76
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Teach OSLib about EABI
This introduces a new asmtype to defmod which invokes the correct
GCC for the task. It may be necessary to perform further surgery
to defmod's assembler generation to address places where the EABI
calling conventions don't match APCS-32 (note that there is no
floating point involved here, so that's one headache avoided).
Update the OSLib build system to allow building for an EABI target.
diff --git a/arm-riscos-gnueabihf/Makefile b/arm-riscos-gnueabihf/Makefile
index 1a9b4a2..6c53c9b 100644
--- a/arm-riscos-gnueabihf/Makefile
+++ b/arm-riscos-gnueabihf/Makefile
@@ -115,7 +115,7 @@ $(BUILDSTEPS)/ccres.d: $(BUILDSTEPS)/oslib.d $(SOURCESDIR)/$(UPSTREAM_CCRES_TARB
$(BUILDSTEPS)/oslib.d: $(BUILDSTEPS)/gcc.d $(SOURCESDIR)/$(UPSTREAM_OSLIB_TARBALL)
tar -C $(BUILDDIR) -xaf $(SOURCESDIR)/$(UPSTREAM_OSLIB_TARBALL)
for p in `ls $(RECIPES)/patches/oslib/*.p` ; do patch -d $(BUILDDIR)/oslib -p0 <$$p ; done
- cd $(BUILDDIR)/oslib && GCCSDK_INSTALL_ENV=$(PREFIX)/env GCCSDK_INSTALL_CROSSBIN=$(PREFIX)/cross/bin make install
+ cd $(BUILDDIR)/oslib && GCCSDK_INSTALL_ENV=$(PREFIX)/env GCCSDK_INSTALL_CROSSBIN=$(PREFIX)/cross/bin make install-elfeabi
touch $@
###
diff --git a/arm-riscos-gnueabihf/recipes/patches/oslib/buildsystem-elfeabi.p b/arm-riscos-gnueabihf/recipes/patches/oslib/buildsystem-elfeabi.p
new file mode 100644
index 0000000..a729f9e
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/patches/oslib/buildsystem-elfeabi.p
@@ -0,0 +1,144 @@
+Index: Source/Makefile
+===================================================================
+--- Source/Makefile (revision 477)
++++ Source/Makefile (working copy)
+@@ -3,8 +3,8 @@
+ # already be built upfront.
+ # Written by OSLib Development Team.
+
+-# Build type: CROSSGCC_AOF, CROSSGCC_ELF (default), [NORCROFT_AOF: not
+-# supported yet]
++# Build type: CROSSGCC_AOF, CROSSGCC_ELF (default), CROSSGCC_ELFEABI,
++# [NORCROFT_AOF: not supported yet]
+ export BUILDTYPE ?= CROSSGCC_ELF
+ # Possible values: "SOFTFPU" (e.g. for UnixLib usage), "HARDFPU" (e.g. for
+ # SharedCLibrary usage) and "MODULE" (latter also meaning HARDFPU but the
+@@ -12,9 +12,10 @@
+ export ELFOBJECTTYPE ?= SOFTFPU
+
+ ifeq ($(BUILDTYPE),CROSSGCC_ELF)
++else ifeq ($(BUILDTYPE),CROSSGCC_ELFEABI)
+ else ifeq ($(BUILDTYPE),CROSSGCC_AOF)
+ else
+-$(error Unknown BUILDTYPE value, possible values are CROSSGCC_AOF and CROSSGCC_ELF)
++$(error Unknown BUILDTYPE value, possible values are CROSSGCC_AOF, CROSSGCC_ELF, and CROSSGCC_ELFEABI)
+ endif
+ include Makefile.setup.$(BUILDTYPE)
+
+Index: Source/Makefile.inc
+===================================================================
+--- Source/Makefile.inc (revision 477)
++++ Source/Makefile.inc (working copy)
+@@ -65,6 +65,9 @@
+ ifeq ($(BUILDTYPE),CROSSGCC_ELF)
+ .ELFHdr.Hdr:
+ if [ -s "$<" ]; then $(CP) $< $@; fi
++else ifeq ($(BUILDTYPE),CROSSGCC_ELFEABI)
++.ELFHdr.Hdr:
++ if [ -s "$<" ]; then $(CP) $< $@; fi
+ else
+ .AOFHdr.Hdr:
+ if [ -s "$<" ]; then $(CP) $< $@; fi
+@@ -98,6 +101,9 @@
+ ifeq ($(BUILDTYPE),CROSSGCC_ELF)
+ .gas.o:
+ $(AS) -o $@ $<
++else ifeq ($(BUILDTYPE),CROSSGCC_ELFEABI)
++.gas.o:
++ $(AS) -o $@ $<
+ else
+ .asm.o:
+ $(AS) -o $@ $<
+Index: Source/Makefile.setup.CROSSGCC_ELFEABI
+===================================================================
+--- Source/Makefile.setup.CROSSGCC_ELFEABI (nonexistent)
++++ Source/Makefile.setup.CROSSGCC_ELFEABI (working copy)
+@@ -0,0 +1,62 @@
++# Settings for ELF building
++
++ifndef GCCSDK_INSTALL_CROSSBIN
++$(error Environment variable GCCSDK_INSTALL_CROSSBIN is not defined)
++endif
++ifndef GCCSDK_INSTALL_ENV
++$(error Environment variable GCCSDK_INSTALL_ENV is not defined)
++endif
++
++ifeq ($(ELFOBJECTTYPE),SOFTFPU)
++CCFLAGS = -mfloat-abi=soft
++DEFMODFLAGS = -float-abi soft
++else ifeq ($(ELFOBJECTTYPE),HARDFPU)
++CCFLAGS = -mlibscl
++DEFMODFLAGS = -float-abi hard
++else ifeq ($(ELFOBJECTTYPE),MODULE)
++CCFLAGS = -mmodule
++DEFMODFLAGS = -float-abi hard
++else
++$(error Unknown ELFOBJECTTYPE value, possible values are SOFTFPU, HARDFPU and MODULE)
++endif
++
++export SOURCEDIR := $(abspath .)
++export BINDIR := $(SOURCEDIR)/../Bin
++export BUILDDIR := $(SOURCEDIR)/../Build
++export RELEASEDIR := $(SOURCEDIR)/../Release
++export RELEASEBINDIR := $(SOURCEDIR)/../Release/$(BUILDTYPE)/$(ELFOBJECTTYPE)
++export EXAMPLESDIR := $(SOURCEDIR)/../examples
++export DOCSDIR := $(SOURCEDIR)/../docs
++
++export TOPHEADERDIR := $(BUILDDIR)/Header
++export HEADERDIR := $(TOPHEADERDIR)/oslib
++export CSTRONGDIR := $(BUILDDIR)/CStrong
++export VAPIDIR := $(BUILDDIR)/\!Vala/vapi
++export VAPIHDIR := $(BUILDDIR)/vapih
++export OBJDIR := $(BUILDDIR)/Objs
++export OBJEXCEPTDIR := $(BUILDDIR)/Objs/Exceptions
++export OSLIBSUPPORTDIR := $(BUILDDIR)/OSLibSupport
++
++export BYTEWIDE := $(SOURCEDIR)/ByteWide
++export DEFMOD := $(BINDIR)/defmod -asmtype gccelfeabi $(DEFMODFLAGS)
++export REDUCEAOF := @echo Not needed for ELF build: reduceaof
++export BINDHELP := $(BINDIR)/bindhelp
++
++export PATH := $(GCCSDK_INSTALL_CROSSBIN):$(PATH)
++
++export CC := arm-riscos-gnueabihf-gcc $(CCFLAGS)
++export CXX := arm-riscos-gnueabihf-g++ $(CCFLAGS)
++export AS := arm-riscos-gnueabihf-gcc -c -xassembler-with-cpp $(CCFLAGS) -I.. -I$(SOURCEDIR)/Types
++export LIBFILE := arm-riscos-gnueabihf-ar rs
++export MKDIR := mkdir -p
++export RM := rm -rf
++export CP := cp -r
++export INSTALL := $(GCCSDK_INSTALL_ENV)/ro-install
++
++export ASMEXT := .gas
++export EXEEXT := ,e1f
++export LIBSUFFIX := a
++
++export OSLIBLIB := $(BUILDDIR)/libOSLib32.$(LIBSUFFIX)
++export OSLIBSUPPORTLIB := $(OSLIBSUPPORTDIR)/libOSLibSupport32.$(LIBSUFFIX)
++export OSLIBCSTRONG := $(BUILDDIR)/OSLib,3d6
+Index: Makefile
+===================================================================
+--- Makefile (revision 477)
++++ Makefile (working copy)
+@@ -29,6 +29,10 @@
+ install-elf: oslib-elf
+ $(MAKE) -C Source install BUILDTYPE=CROSSGCC_ELF
+
++# Installs the ELF headers & library in GCCSDK environment.
++install-elfeabi: oslib-elfeabi
++ $(MAKE) -C Source install BUILDTYPE=CROSSGCC_ELFEABI
++
+ # Installs the AOF headers & library in GCCSDK environment.
+ install-aof: oslib-aof
+ $(MAKE) -C Source install BUILDTYPE=CROSSGCC_AOF
+@@ -49,6 +53,10 @@
+ $(MAKE) -C Source oslib BUILDTYPE=CROSSGCC_ELF
+ $(MAKE) -C Source oslibsupport BUILDTYPE=CROSSGCC_ELF
+
++oslib-elfeabi: tools
++ $(MAKE) -C Source oslib BUILDTYPE=CROSSGCC_ELFEABI
++ $(MAKE) -C Source oslibsupport BUILDTYPE=CROSSGCC_ELFEABI
++
+ vapis: tools
+ $(MAKE) -C Source vapis BUILDTYPE=CROSSGCC_ELF
+
diff --git a/arm-riscos-gnueabihf/recipes/patches/oslib/defmod-elfeabi.p b/arm-riscos-gnueabihf/recipes/patches/oslib/defmod-elfeabi.p
new file mode 100644
index 0000000..97e15f8
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/patches/oslib/defmod-elfeabi.p
@@ -0,0 +1,84 @@
+Index: Tools/DefMod2/assembler.c
+===================================================================
+--- Tools/DefMod2/assembler.c (revision 477)
++++ Tools/DefMod2/assembler.c (working copy)
+@@ -1242,6 +1242,21 @@
+ goto finish;
+ break;
+ }
++ case AsmType_eGCCELFEABI:
++ {
++ const char *floatABI = (FloatABI == FloatABI_eSoft) ? "soft" : "hard";
++ if (!apcs32)
++ {
++ fprintf(stderr, "EABI does not support APCS-26.");
++ goto finish;
++ }
++ if ((rc = sprintf (cmd,
++ "arm-riscos-gnueabihf-gcc -c -xassembler -mfloat-abi=%s -o %s %s",
++ floatABI,
++ name2, name1)) < 0)
++ goto finish;
++ break;
++ }
+ default:
+ fprintf (stderr, "Unknown assembler type\n");
+ goto finish;
+Index: Tools/DefMod2/assembler.h
+===================================================================
+--- Tools/DefMod2/assembler.h (revision 477)
++++ Tools/DefMod2/assembler.h (working copy)
+@@ -22,8 +22,9 @@
+ AsmType_eGCCAOF, /* Assembler used in GCCSDK 3.4 (AOF) release, called
+ 'as' (predecessor of AsAsm). */
+ AsmType_eARMASM, /* ARM's assembler. */
+- AsmType_eGCCELF /* Assembler used in GCCSDK 4 (ELF) release, called
++ AsmType_eGCCELF, /* Assembler used in GCCSDK 4 (ELF) release, called
+ 'gas' (GNU binutils assembler). */
++ AsmType_eGCCELFEABI /* Assembler used in EABI-capable GCCSDK */
+ } AsmType_e;
+
+ typedef enum
+@@ -37,7 +38,7 @@
+ extern AsmType_e AsmType;
+ extern FloatABI_e FloatABI;
+
+-#define GASSyntax (AsmType == AsmType_eGCCELF)
++#define GASSyntax (AsmType == AsmType_eGCCELF || AsmType == AsmType_eGCCELFEABI)
+
+ /*if |separate|, output is to the directory |output|; otherwise, to the file |file|.*/
+ extern os_error *assembler_output (FILE *file, const char *title, const char *author, lookup_t types, lookup_t swis, osbool separate, osbool apcs32, char *output);
+Index: Tools/DefMod2/defmod.y
+===================================================================
+--- Tools/DefMod2/defmod.y (revision 477)
++++ Tools/DefMod2/defmod.y (working copy)
+@@ -1179,7 +1179,7 @@
+ "[-o <output-dir> | > <output-file>] "
+ "[-byte_wide <byte-wide-file>] "
+ "[-26bit | -32bit] "
+- "[-asmtype [objasm | asasmaof | asasmelf | gccaof | armasm | gccelf]] "
++ "[-asmtype [objasm | asasmaof | asasmelf | gccaof | armasm | gccelf | gccelfeabi]] "
+ "[-float-abi [soft | hard]] "
+ "< <module-interface-file>\r"
+ "Purpose: generate output from a module interface file\r"
+@@ -1203,6 +1203,7 @@
+ "\tgccaof\t\t" "...use GCC AOF toolkit (GCCSDK 3.4 only)\r"
+ "\tarmasm\t\t" "...use ARM ASM\r"
+ "\tgccelf\t\t" "...use GCC ELF toolkit (GCCSDK 4 only)\r"
++ "\tgccelfeabi\t\t" "...use GCC EABI ELF toolkit (GCCSDK 8+ only)\r"
+ "-float-abi\t\t" "marks object files which float-abi is in use\r"
+ "\tsoft\t\t" "...soft-float, no FP instructions used\r"
+ "\thard\t\t" "...hard-float, FP instructions can be used\r"
+@@ -1345,9 +1346,11 @@
+ AsmType = AsmType_eARMASM;
+ else if (strcmp (argv[i], "gccelf") == 0)
+ AsmType = AsmType_eGCCELF;
++ else if (strcmp (argv[i], "gccelfeabi") == 0)
++ AsmType = AsmType_eGCCELFEABI;
+ else
+ {
+- fprintf (stderr, "Unknown option value %s for -asmtype (only \"objasm\", \"asasmaof\", \"asasmelf\", \"armarm\", \"gccaof\" and \"gccelf\" are known)\n", argv[i]);
++ fprintf (stderr, "Unknown option value %s for -asmtype (only \"objasm\", \"asasmaof\", \"asasmelf\", \"armarm\", \"gccaof\", \"gccelf\" and \"gccelfeabi\" are known)\n", argv[i]);
+ Parse_Error = TRUE;
+ goto finish;
+ }
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=e8d3950da344b454...
commit e8d3950da344b454e74e7b6e46a35c18724561ea
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Fix OS ABI check when building elf2aif for EABI
Binaries built with the arm-riscos-gnueabihf toolchain have an
OS ABI of none (i.e. Sys-V) in the ELF header. elf2aif expected
the declared ABI to be ARM as that is what the previous tooling
emitted. Fix up this check to reflect the new reality.
diff --git a/arm-riscos-gnueabihf/recipes/patches/gccsdk/elf2aif-no-abi-check.p b/arm-riscos-gnueabihf/recipes/patches/gccsdk/elf2aif-no-abi-check.p
new file mode 100644
index 0000000..3ad6372
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/patches/gccsdk/elf2aif-no-abi-check.p
@@ -0,0 +1,16 @@
+Index: elf2aif/src/elf2aif.c
+===================================================================
+--- elf2aif/src/elf2aif.c (revision 7698)
++++ elf2aif/src/elf2aif.c (working copy)
+@@ -201,7 +201,11 @@
+ return EXIT_FAILURE;
+ }
+
++#ifndef __ARM_EABI__
+ if (elf_ehdr.e_ident[EI_OSABI] != ELFOSABI_ARM)
++#else
++ if (elf_ehdr.e_ident[EI_OSABI] != ELFOSABI_NONE)
++#endif
+ {
+ fprintf (stderr, "ELF file '%s' is not for ARM\n", elf_filename);
+ return EXIT_FAILURE;
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=ae01cbe542362cc9...
commit ae01cbe542362cc99596d4e07c205659200de425
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Fetch and build additional tools
Specifically: asasm, elf2aif, ln, mkres
diff --git a/arm-riscos-gnueabihf/Makefile b/arm-riscos-gnueabihf/Makefile
index 0c9eadb..1a9b4a2 100644
--- a/arm-riscos-gnueabihf/Makefile
+++ b/arm-riscos-gnueabihf/Makefile
@@ -2,10 +2,14 @@
UPSTREAM_GCCSDK_VERSION := 7698
UPSTREAM_GCCSDK_TARBALL := gccsdk$(UPSTREAM_GCCSDK_VERSION).tar.gz
UPSTREAM_GCCSDK_URI := svn://svn.riscos.info/gccsdk/trunk/autobuilder/develop/gcc@$(UPSTREAM_GCCSDK_VERSION)
-UPSTREAM_GCCSDK_AMP_URI := svn://svn.riscos.info/gccsdk/trunk/gcc4/recipe/patches/automake-for-binutils@$(UPSTREAM_GCCSDK_VERSION)
-UPSTREAM_GCCSDK_LD_URI := svn://svn.riscos.info/gccsdk/trunk/gcc4/riscos/soloader/dynamic/ld.so-1.9.9@$(UPSTREAM_GCCSDK_VERSION)
UPSTREAM_GCCSDK_SGP_URI := svn://svn.riscos.info/gccsdk/trunk/gcc4/setup-gccsdk-params@$(UPSTREAM_GCCSDK_VERSION)
+UPSTREAM_GCCSDK_AMP_URI := svn://svn.riscos.info/gccsdk/trunk/gcc4/recipe/patches/automake-for-binutils@$(UPSTREAM_GCCSDK_VERSION)
UPSTREAM_GCCSDK_UNIXLIB_URI := svn://svn.riscos.info/gccsdk/trunk/gcc4/recipe/files/gcc/libunixlib@$(UPSTREAM_GCCSDK_VERSION)
+UPSTREAM_GCCSDK_LD_URI := svn://svn.riscos.info/gccsdk/trunk/gcc4/riscos/soloader/dynamic/ld.so-1.9.9@$(UPSTREAM_GCCSDK_VERSION)
+UPSTREAM_GCCSDK_ASASM_URI := svn://svn.riscos.info/gccsdk/trunk/tools/asasm@$(UPSTREAM_GCCSDK_VERSION)
+UPSTREAM_GCCSDK_ELF2AIF_URI := svn://svn.riscos.info/gccsdk/trunk/gcc4/riscos/elf2aif@$(UPSTREAM_GCCSDK_VERSION)
+UPSTREAM_GCCSDK_LN_URI := svn://svn.riscos.info/gccsdk/trunk/gcc4/riscos/ln@$(UPSTREAM_GCCSDK_VERSION)
+UPSTREAM_GCCSDK_MKRESFS_URI := svn://svn.riscos.info/gccsdk/trunk/gcc4/riscos/mkresfs@$(UPSTREAM_GCCSDK_VERSION)
# OSLib 7.00
UPSTREAM_OSLIB_VERSION := 700
@@ -147,10 +151,14 @@ $(BUILDSTEPS)/gccsdk-srcdir.d: $(BUILDSTEPS)/buildsteps.d $(SOURCESDIR)/$(UPSTRE
$(SOURCESDIR)/$(UPSTREAM_GCCSDK_TARBALL):
svn export $(UPSTREAM_GCCSDK_URI) $(SOURCESDIR)/gccsdk/gcc
- svn export $(UPSTREAM_GCCSDK_AMP_URI) $(SOURCESDIR)/gccsdk/automake
- svn export $(UPSTREAM_GCCSDK_LD_URI) $(SOURCESDIR)/gccsdk/ld
svn export $(UPSTREAM_GCCSDK_SGP_URI) $(SOURCESDIR)/gccsdk/
+ svn export $(UPSTREAM_GCCSDK_AMP_URI) $(SOURCESDIR)/gccsdk/automake
svn export $(UPSTREAM_GCCSDK_UNIXLIB_URI) $(SOURCESDIR)/gccsdk/libunixlib
+ svn export $(UPSTREAM_GCCSDK_LD_URI) $(SOURCESDIR)/gccsdk/ld
+ svn export $(UPSTREAM_GCCSDK_ASASM_URI) $(SOURCESDIR)/gccsdk/asasm
+ svn export $(UPSTREAM_GCCSDK_ELF2AIF_URI) $(SOURCESDIR)/gccsdk/elf2aif
+ svn export $(UPSTREAM_GCCSDK_LN_URI) $(SOURCESDIR)/gccsdk/ln
+ svn export $(UPSTREAM_GCCSDK_MKRESFS_URI) $(SOURCESDIR)/gccsdk/mkresfs
tar -C $(SOURCESDIR) -caf $@ gccsdk
$(SOURCESDIR)/$(UPSTREAM_OSLIB_TARBALL):
diff --git a/arm-riscos-gnueabihf/recipes/files/gccsdk/Makefile b/arm-riscos-gnueabihf/recipes/files/gccsdk/Makefile
index 5f2740b..4e3467b 100644
--- a/arm-riscos-gnueabihf/recipes/files/gccsdk/Makefile
+++ b/arm-riscos-gnueabihf/recipes/files/gccsdk/Makefile
@@ -247,14 +247,38 @@ cross-gcc-built: cross-gcc-configured
cd $(BUILDDIR)/cross-gcc && PATH="$(PREFIX_BUILDTOOL_GCC)/bin:$(PREFIX_CROSS)/bin:$(PATH)" && $(MAKE) $(GCC_BUILD_FLAGS) && $(MAKE) install
touch $(BUILDSTEPSDIR)/$@
-# Build the RISC OS related tools (cmunge, elf2aif, asasm, etc) cross:
-# XXX: currently, this just builds ld -- what more do we need?
+# Build the RISC OS related tools (elf2aif, asasm, etc) cross:
cross-riscostools-built: cross-gcc-built
+ @# LD
-rm -rf $(BUILDDIR)/cross-ld
mkdir -p $(BUILDDIR)/cross-ld
- cd $(ROOT)/ld && PATH="$(PREFIX_CROSS)/bin:$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" autoreconf --install
+ cd $(ROOT)/ld && PATH="$(PREFIX_CROSS)/bin:$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" autoreconf -f --install
cd $(BUILDDIR)/cross-ld && PATH="$(PREFIX_CROSS)/bin:$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" CC=$(GCCSDK_INSTALL_CROSSBIN)/$(TARGET)-gcc $(ROOT)/ld/configure --prefix=$(PREFIX_CROSS)/$(TARGET) --host=$(TARGET) --target=$(TARGET)
cd $(BUILDDIR)/cross-ld && PATH="$(PREFIX_CROSS)/bin:$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" make install
+ @# asasm
+ -rm -rf $(BUILDDIR)/cross-asasm
+ mkdir -p $(BUILDDIR)/cross-asasm
+ cd $(ROOT)/asasm && PATH="$(PREFIX_CROSS)/bin:$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" ACLOCAL='aclocal -I $(ROOT)/asasm/m4' autoreconf -f --install
+ cd $(BUILDDIR)/cross-asasm && PATH="$(PREFIX_CROSS)/bin:$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" $(ROOT)/asasm/configure --prefix=$(PREFIX_CROSS) --target=$(TARGET) --disable-building-tools
+ cd $(BUILDDIR)/cross-asasm && PATH="$(PREFIX_CROSS)/bin:$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" make install-minimum
+ @# elf2aif
+ -rm -rf $(BUILDDIR)/cross-elf2aif
+ mkdir -p $(BUILDDIR)/cross-elf2aif
+ cd $(ROOT)/elf2aif && PATH="$(PREFIX_CROSS)/bin:$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" autoreconf -f --install
+ cd $(BUILDDIR)/cross-elf2aif && PATH="$(PREFIX_CROSS)/bin:$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" $(ROOT)/elf2aif/configure --prefix=$(PREFIX_CROSS) --target=$(TARGET)
+ cd $(BUILDDIR)/cross-elf2aif && PATH="$(PREFIX_CROSS)/bin:$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" make install
+ @# ln
+ -rm -rf $(BUILDDIR)/cross-ln
+ mkdir -p $(BUILDDIR)/cross-ln
+ cd $(ROOT)/ln && PATH="$(PREFIX_CROSS)/bin:$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" autoreconf -f --install
+ cd $(BUILDDIR)/cross-ln && PATH="$(PREFIX_CROSS)/bin:$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" $(ROOT)/ln/configure --prefix=$(PREFIX_CROSS) --target=$(TARGET)
+ cd $(BUILDDIR)/cross-ln && PATH="$(PREFIX_CROSS)/bin:$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" make install
+ @# mkresfs
+ -rm -rf $(BUILDDIR)/cross-mkresfs
+ mkdir -p $(BUILDDIR)/cross-mkresfs
+ cd $(ROOT)/mkresfs && PATH="$(PREFIX_CROSS)/bin:$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" autoreconf -f --install
+ cd $(BUILDDIR)/cross-mkresfs && PATH="$(PREFIX_CROSS)/bin:$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" $(ROOT)/mkresfs/configure --prefix=$(PREFIX_CROSS) --target=$(TARGET)
+ cd $(BUILDDIR)/cross-mkresfs && PATH="$(PREFIX_CROSS)/bin:$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" make install
touch $(BUILDSTEPSDIR)/$@
# -- Source unpacking.
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=44e9cb649a93b4f6...
commit 44e9cb649a93b4f62b3f962e7be31cef00987541
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Don't pull in ARMv7-specific memcpy() and friends.
Hiding this behind ARM_EABI probably isn't the complete answer as
the calling convention doesn't have much to say about the platform
the end result is run on.
diff --git a/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-no-armv7-memcpy.p b/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-no-armv7-memcpy.p
new file mode 100644
index 0000000..c89d6ab
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-no-armv7-memcpy.p
@@ -0,0 +1,34 @@
+Index: libunixlib/Makefile.am
+===================================================================
+--- libunixlib/Makefile.am (revision 7698)
++++ libunixlib/Makefile.am (working copy)
+@@ -1002,18 +1002,11 @@
+ string/strtok.c \
+ string/swab.c \
+ string/_strcpy.s
+-if ARM_EABI
+ string_src += \
+- string/_memcpymove-v7l.s \
+- string/_memset-v7l.s \
+- string/_strlen-v7l.s
+-else
+-string_src += \
+ string/_memcpy.s \
+ string/_memset.s \
+ string/_strlen.s
+ endif
+-endif
+ string_src += \
+ string/memccpy.c \
+ string/memchr.c \
+@@ -1029,10 +1022,8 @@
+ string/strtok_r.c \
+ string/_ffs.s \
+ string/_ffsll.s
+-if !ARM_EABI
+ string_src += \
+ string/mempcpy.c
+-endif
+
+ if UNIXLIB_BUILDING_SCL
+ sys_src =
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=5614c157989873ef...
commit 5614c157989873efdb53cb5633ee9eb461ec814c
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Fix initial stack allocation for EABI and soft FP.
In this case, there are no VFP registers to reserve space for at
the top of the application stack. Thus, the stack pointer points
at the top of the stack when we ask ARMEABISupport to give us the
stack handle. Unfortunately, despite the top address being given
to us by ARMEABISupport in the first place, it does not consider
the top of the stack to be part of the stack's storage space and
thus we fail to obtain our stack handle and the application aborts.
Work around this by discarding the top N bytes of the stack when
EABI and soft FP are active. The resulting stack pointer will be
aligned to a multiple of 8 bytes in the usual way for AAPCS.
Additionally, resolve another stack imbalance in an error path
that was spotted while working through this.
diff --git a/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-initial-sp.p b/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-initial-sp.p
new file mode 100644
index 0000000..f3309c2
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-initial-sp.p
@@ -0,0 +1,31 @@
+Index: libunixlib/sys/_syslib.s
+===================================================================
+--- libunixlib/sys/_syslib.s (revision 7698)
++++ libunixlib/sys/_syslib.s (working copy)
+@@ -396,8 +396,9 @@
+ SWI XOS_ReadVarVal @ Read value of progname$HeapMax
+ BVS t08
+ TEQ v1, #1 @ Should be a number variable
+- LDREQ v2, [sp], #4
++ LDREQ v2, [sp]
+ MOVEQ v2, v2, LSL#20 @ Convert MB into bytes
++ ADD sp, sp, #4
+
+ @ v2 = size of DA area
+ t08:
+@@ -512,7 +513,15 @@
+ MOVCC a1, #ERR_NO_FPE
+ BCC __exit_with_error_num
+ #endif
++#else
++#ifdef __ARM_EABI__
++ @ EABI with software FP. Burn the top of the stack to appease
++ @ ARMEABISupport (which does not consider the stack top address
++ @ as part of the stack).
++ SUB sp, sp, #4
++ BIC sp, sp, #7 @ AAPCS wants 8 byte alignment
+ #endif
++#endif
+
+ @ We need to create this now so that we have its address to give to
+ @ the callback handler, but we can initialise it later.
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=702073888df04286...
commit 702073888df04286767540c3159c2c6e385a761d
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Build riscos-ld for armv4
diff --git a/arm-riscos-gnueabihf/recipes/patches/gccsdk/ld-armv4.p b/arm-riscos-gnueabihf/recipes/patches/gccsdk/ld-armv4.p
new file mode 100644
index 0000000..ae85eb0
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/patches/gccsdk/ld-armv4.p
@@ -0,0 +1,13 @@
+Index: ld/d-link/Makefile.am
+===================================================================
+--- ld/d-link/Makefile.am (revision 7698)
++++ ld/d-link/Makefile.am (working copy)
+@@ -68,7 +68,7 @@
+
+ ld_riscos_eabihf_so_CPPFLAGS = -I$(top_srcdir)/d-link -I$(top_srcdir)/d-link/riscos \
+ -DNO_UNDERSCORE -DVERBOSE_DLINKER -D__TARGET_SOLOADER__
+-ld_riscos_eabihf_so_CFLAGS = -fPIC -O4 -Wall -std=gnu99 -march=armv7-a+fp+neon
++ld_riscos_eabihf_so_CFLAGS = -fPIC -O4 -Wall -std=gnu99 -march=armv4
+ ld_riscos_eabihf_so_LDFLAGS = --shared -Wl,--no-undefined -nostdlib -nostartfiles -Wl,-e -Wl,_dl_start \
+ -Wl,-soname -Wl,ld-riscos/so/2
+
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=2021fafbbafbaa7f...
commit 2021fafbbafbaa7f8a53ac290b431179c6ec038f
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Disable halfword accesses by default.
We don't want these at all until such time as we drop support for
the Risc PC. Due to the unique way that its bus operates (it was
designed for armv3 parts), 16bit accesses fail horribly, even if
the CPU supports armv4 (like StrongARM does). Disabling this by
default ensures that everything built by this toolchain should
run happily on such systems (unless someone explicitly opts in to
LDRH/STRH generation by passing -mhalfword-accesses). Note that
other armv4 access instructions (such as LDRSB) are not affected
by this option at all.
diff --git a/arm-riscos-gnueabihf/recipes/patches/gccsdk/gcc-default-no-halfword-access.p b/arm-riscos-gnueabihf/recipes/patches/gccsdk/gcc-default-no-halfword-access.p
new file mode 100644
index 0000000..400341f
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/patches/gccsdk/gcc-default-no-halfword-access.p
@@ -0,0 +1,13 @@
+Index: gcc/gcc.config.arm.arm.opt.p
+===================================================================
+--- gcc/gcc.config.arm.arm.opt.p (nonexistent)
++++ gcc/gcc.config.arm.arm.opt.p (working copy)
+@@ -5,7 +5,7 @@
+ that may trigger Cortex-M3 errata.
+
+ +mhalfword-access
+-+Target Report Var(halfword_access) Init(1)
+++Target Report Var(halfword_access) Init(0)
+ +Enable halfword memory accesses.
+ +
+ munaligned-access
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=1adf75a71b1a8dde...
commit 1adf75a71b1a8dde55047f8da8a7ba4e1436d257
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Add a -mhalfword-access flag to GCC.
This defaults to "on", as that's what most sane people want when
building for armv4 or later.
diff --git a/arm-riscos-gnueabihf/recipes/patches/gccsdk/gcc-add-mhalfword-access.p b/arm-riscos-gnueabihf/recipes/patches/gccsdk/gcc-add-mhalfword-access.p
new file mode 100644
index 0000000..43061b9
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/patches/gccsdk/gcc-add-mhalfword-access.p
@@ -0,0 +1,153 @@
+Index: gcc/gcc.config.arm.arm.h.p
+===================================================================
+--- gcc/gcc.config.arm.arm.h.p (nonexistent)
++++ gcc/gcc.config.arm.arm.h.p (working copy)
+@@ -0,0 +1,33 @@
++--- gcc/config/arm/arm.h.orig 2020-07-23 07:35:17.344384552 +0100
+++++ gcc/config/arm/arm.h 2022-05-28 22:48:25.064918314 +0100
++@@ -1338,7 +1338,9 @@
++ : (TARGET_IWMMXT && (CLASS) == IWMMXT_REGS) \
++ ? coproc_secondary_reload_class (MODE, X, TRUE) \
++ : TARGET_32BIT \
++- ? (((MODE) == HImode && ! arm_arch4 && true_regnum (X) == -1) \
+++ ? (((MODE) == HImode && \
+++ (!arm_arch4 || !halfword_access) && \
+++ true_regnum (X) == -1) \
++ ? GENERAL_REGS : NO_REGS) \
++ : THUMB_SECONDARY_OUTPUT_RELOAD_CLASS (CLASS, MODE, X))
++
++@@ -1353,7 +1355,7 @@
++ (((CLASS) == IWMMXT_REGS || (CLASS) == IWMMXT_GR_REGS) \
++ && CONSTANT_P (X)) \
++ ? GENERAL_REGS : \
++- (((MODE) == HImode && ! arm_arch4 \
+++ (((MODE) == HImode && (!arm_arch4 || !halfword_access) \
++ && (MEM_P (X) \
++ || ((REG_P (X) || GET_CODE (X) == SUBREG) \
++ && true_regnum (X) == -1))) \
++@@ -2016,7 +2018,9 @@
++ done, UNKNOWN if none. */
++ #define LOAD_EXTEND_OP(MODE) \
++ (TARGET_THUMB ? ZERO_EXTEND : \
++- ((arm_arch4 || (MODE) == QImode) ? ZERO_EXTEND \
+++ (((arm_arch4 && (halfword_access || (MODE) != HImode)) || \
+++ (MODE) == QImode) \
+++ ? ZERO_EXTEND \
++ : ((BYTES_BIG_ENDIAN && (MODE) == HImode) ? SIGN_EXTEND : UNKNOWN)))
++
++ /* Nonzero if access to memory by bytes is slow and undesirable. */
+Index: gcc/gcc.config.arm.arm.md.p
+===================================================================
+--- gcc/gcc.config.arm.arm.md.p (revision 7698)
++++ gcc/gcc.config.arm.arm.md.p (working copy)
+@@ -8,6 +8,42 @@
+ (IP_REGNUM 12) ; Scratch register
+ (SP_REGNUM 13) ; Stack pointer
+ (LR_REGNUM 14) ; Return address register
++@@ -5546,7 +5547,7 @@
++ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand")))]
++ "TARGET_EITHER"
++ {
++- if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
+++ if (TARGET_ARM && (!arm_arch4 || !halfword_access) && MEM_P (operands[1]))
++ {
++ emit_insn (gen_movhi_bytes (operands[0], operands[1]));
++ DONE;
++@@ -5574,7 +5575,7 @@
++ (define_insn "*arm_zero_extendhisi2"
++ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
++ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
++- "TARGET_ARM && arm_arch4 && !arm_arch6"
+++ "TARGET_ARM && arm_arch4 && halfword_access && !arm_arch6"
++ "@
++ #
++ ldrh%?\\t%0, %1"
++@@ -5735,7 +5736,7 @@
++ emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
++ DONE;
++ }
++- if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
+++ if (MEM_P (operands[1]) && TARGET_ARM && (!arm_arch4 || !halfword_access))
++ {
++ emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
++ DONE;
++@@ -5813,7 +5814,7 @@
++ (define_insn "*arm_extendhisi2"
++ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
++ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
++- "TARGET_ARM && arm_arch4 && !arm_arch6"
+++ "TARGET_ARM && arm_arch4 && halfword_access && !arm_arch6"
++ "@
++ #
++ ldrsh%?\\t%0, %1"
+ @@ -6693,7 +6694,7 @@
+ (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (unspec:SI [(match_operand:SI 2 "" "X")]
+@@ -17,3 +53,49 @@
+ "ldr%?\\t%0, [%1,%2]"
+ [(set_attr "type" "load_4")]
+ )
++@@ -6845,7 +6846,7 @@
++ (define_expand "storehi_single_op"
++ [(set (match_operand:HI 0 "memory_operand")
++ (match_operand:HI 1 "general_operand"))]
++- "TARGET_32BIT && arm_arch4"
+++ "TARGET_32BIT && arm_arch4 && halfword_access"
++ "
++ if (!s_register_operand (operands[1], HImode))
++ operands[1] = copy_to_mode_reg (HImode, operands[1]);
++@@ -6865,7 +6865,7 @@
++ {
++ if (MEM_P (operands[0]))
++ {
++- if (arm_arch4)
+++ if (arm_arch4 && halfword_access)
++ {
++ emit_insn (gen_storehi_single_op (operands[0], operands[1]));
++ DONE;
++@@ -6905,15 +6905,15 @@
++ emit_insn (gen_movsi (reg, GEN_INT (val)));
++ operands[1] = gen_lowpart (HImode, reg);
++ }
++- else if (arm_arch4 && optimize && can_create_pseudo_p ()
++- && MEM_P (operands[1]))
+++ else if (arm_arch4 && halfword_access && optimize
+++ && can_create_pseudo_p () && MEM_P (operands[1]))
++ {
++ rtx reg = gen_reg_rtx (SImode);
++
++ emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
++ operands[1] = gen_lowpart (HImode, reg);
++ }
++- else if (!arm_arch4)
+++ else if (!arm_arch4 || !halfword_access)
++ {
++ if (MEM_P (operands[1]))
++ {
++@@ -7099,7 +7100,7 @@
++ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r")
++ (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))]
++ "TARGET_ARM
++- && arm_arch4 && !TARGET_HARD_FLOAT
+++ && arm_arch4 && halfword_access && !TARGET_HARD_FLOAT
++ && (register_operand (operands[0], HImode)
++ || register_operand (operands[1], HImode))"
++ "@
+Index: gcc/gcc.config.arm.arm.opt.p
+===================================================================
+--- gcc/gcc.config.arm.arm.opt.p (nonexistent)
++++ gcc/gcc.config.arm.arm.opt.p (working copy)
+@@ -0,0 +1,13 @@
++--- gcc/config/arm/arm.opt.orig 2020-07-23 07:35:17.344384552 +0100
+++++ gcc/config/arm/arm.opt 2022-05-28 22:39:28.543576700 +0100
++@@ -271,6 +271,10 @@
++ Avoid overlapping destination and address registers on LDRD instructions
++ that may trigger Cortex-M3 errata.
++
+++mhalfword-access
+++Target Report Var(halfword_access) Init(1)
+++Enable halfword memory accesses.
+++
++ munaligned-access
++ Target Report Var(unaligned_access) Init(2) Save
++ Enable unaligned word and halfword accesses to packed data.
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=004197f1ecc4f963...
commit 004197f1ecc4f9636ee579daa2a5566faba240b4
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Patch UnixLib to build for armv4 when using EABI.
There are a few places where a decision is made at runtime as to
which atomic operations to perform. Modern gas objects to this
scheme if it isn't told about it, resulting in errors from the
assembler and failed builds. Tell gas what we're doing and make
the SWP-present logic depend on the architecture that UnixLib
is being built for (if you build for armv6 or later in EABI
mode, then no runtime decision or SWP instructions will be
emitted).
Additionally, there's a similar case where LDREX/STREX is used
from inline assembler in the __cmpxchg atomic built when
targetting EABI. Make this, too, conditional on building for
armv6 or later.
diff --git a/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-armv4.p b/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-armv4.p
new file mode 100644
index 0000000..1343d13
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/patches/gccsdk/unixlib-armv4.p
@@ -0,0 +1,80 @@
+Index: libunixlib/gcccompat/atomics.c
+===================================================================
+--- libunixlib/gcccompat/atomics.c (revision 7698)
++++ libunixlib/gcccompat/atomics.c (working copy)
+@@ -378,7 +378,7 @@
+ ATOMIC_OP_FETCH(or,(*ptr) |= val,unsigned)
+ ATOMIC_OP_FETCH(nand,(*ptr) = ~((*ptr) & val),unsigned)
+
+-#ifdef __ARM_EABI__
++#if defined(__ARM_EABI__) && defined(__ARM_ARCH) && (__ARM_ARCH >= 6)
+
+ static int __cmpxchg (int oldval, int newval, volatile int *ptr)
+ {
+Index: libunixlib/pthread/_ints.s
+===================================================================
+--- libunixlib/pthread/_ints.s (revision 7698)
++++ libunixlib/pthread/_ints.s (working copy)
+@@ -14,6 +14,15 @@
+ .protected __pthread_enable_ints
+ .global __pthread_protect_unsafe
+
++#if defined(__ARM_ARCH) && (__ARM_ARCH__ < 6)
++ /* Modern gas objects to our runtime-conditional use of LDREX/STREX
++ * in here. If we're building for pre-armv6 architectures, tell gas
++ * that to allow armv6 instructions, but mark the resulting object
++ * as armv4 compatible. */
++ .arch armv6
++ .object_arch armv4
++#endif
++
+ @ Disable context switches by incrementing the semaphore
+ @ May be called from USR or SVC mode
+ NAME __pthread_disable_ints
+@@ -23,7 +32,7 @@
+ LDR a1, .L0 @ =__ul_global
+ PICEQ "LDR a1, [a2, a1]"
+ LDR ip, [a1, #GBL_PTH_CALLEVERY_RMA]
+-#ifdef __ARM_EABI__
++#if defined(__ARM_EABI__) && defined(__ARM_ARCH) && (__ARM_ARCH >= 6)
+ ADD a1, ip, #PTHREAD_CALLEVERY_RMA_WORKSEMAPHORE
+ #else
+ LDR a4, [a1, #GBL_CPU_FLAGS]
+@@ -93,7 +102,7 @@
+ LDR a4, .L2 @ =__ul_global
+ PICEQ "LDR a4, [a1, a4]"
+ LDR ip, [a4, #GBL_PTH_CALLEVERY_RMA]
+-#ifdef __ARM_EABI__
++#if defined(__ARM_EABI__) && defined(__ARM_ARCH) && (__ARM_ARCH >= 6)
+ ADD a1, ip, #PTHREAD_CALLEVERY_RMA_WORKSEMAPHORE
+ #else
+ LDR a2, [a4, #GBL_CPU_FLAGS]
+Index: libunixlib/sys/_syslib.s
+===================================================================
+--- libunixlib/sys/_syslib.s (revision 7698)
++++ libunixlib/sys/_syslib.s (working copy)
+@@ -49,6 +49,15 @@
+ .weak __dynamic_da_max_size
+ .weak __stack_size
+
++#if defined(__ARM_ARCH) && (__ARM_ARCH__ < 6)
++ /* Modern gas objects to our runtime-conditional use of LDREX/STREX
++ * in here. If we're building for pre-armv6 architectures, tell gas
++ * that to allow armv6 instructions, but mark the resulting object
++ * as armv4 compatible. */
++ .arch armv6
++ .object_arch armv4
++#endif
++
+ @ RMEnsure the minimum version of the SharedUnixLibrary we need.
+ @ Now check System modules first as UnixLib package is deprecated.
+ #if !defined(__SOFTFP__) && defined(__VFP_FP__)
+@@ -1414,7 +1423,7 @@
+ @ we go for a straight OS_Exit scenario. Anything better we
+ @ can do ?
+ ADD a3, a4, #GBL_PANIC_MODE
+-#ifndef __ARM_EABI__
++#if !defined(__ARM_EABI__) || !defined(__ARM_ARCH) || (__ARM_ARCH < 6)
+ LDR a2, [a4, #GBL_CPU_FLAGS]
+ TST a2, #__CPUCAP_HAVE_SWP
+ BEQ 0f
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=c428f82587d0c284...
commit c428f82587d0c284aa0217ffdece91808fc292e9
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
Make config.sub identify RISC OS; libtool follows.
The logic in libtool.m4 looks somewhat confused. This is a direct
translation of what was there already to the new world. It may
need further changes to work reliably.
diff --git a/arm-riscos-gnueabihf/recipes/files/gccsdk/config.sub.p b/arm-riscos-gnueabihf/recipes/files/gccsdk/config.sub.p
new file mode 100644
index 0000000..181b56f
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/files/gccsdk/config.sub.p
@@ -0,0 +1,11 @@
+--- config.sub.orig 2022-06-01 07:47:44.364644855 +0100
++++ config.sub 2022-06-01 07:48:02.892796689 +0100
+@@ -135,7 +135,7 @@
+ | linux-newlib* | linux-musl* | linux-uclibc* | uclinux-uclibc* \
+ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
+ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
+- | storm-chaos* | os2-emx* | rtmk-nova*)
++ | storm-chaos* | os2-emx* | rtmk-nova* | riscos-gnu*)
+ basic_machine=$field1
+ os=$maybe_os
+ ;;
diff --git a/arm-riscos-gnueabihf/recipes/patches/gccsdk/libtool.m4.p.p b/arm-riscos-gnueabihf/recipes/patches/gccsdk/libtool.m4.p.p
new file mode 100644
index 0000000..8061b92
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/patches/gccsdk/libtool.m4.p.p
@@ -0,0 +1,119 @@
+Index: gcc/libtool.m4.p
+===================================================================
+--- gcc/libtool.m4.p (revision 7698)
++++ gcc/libtool.m4.p (working copy)
+@@ -5,7 +5,7 @@
+ ])
+ ;;
+ +
+-+ *riscos | *linux-gnueabihf)
+++ *riscos*)
+ + lt_cv_dlopen="dlopen"
+ + lt_cv_dlopen_libs="-ldl"
+ + lt_cv_dlopen_self=yes
+@@ -17,7 +17,7 @@
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+-+*riscos | linux-gnueabihf)
+++*riscos*)
+ + version_type=linux
+ + library_names_spec='${libname}$versuffix.so ${libname}.so$major $libname.so'
+ + soname_spec='${libname}.so$major'
+@@ -32,7 +32,7 @@
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+-+ *linux-gnueabihf)
+++ riscos-gnu*)
+ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+@@ -48,7 +48,7 @@
+ esac
+ else
+ case $host_os in
+-+ linux-gnueabihf)
+++ riscos-gnu*)
+ + # RISC OS
+ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+@@ -61,7 +61,7 @@
+ ;;
+ vxworks*)
+ ;;
+-+ *linux-gnueabihf)
+++ riscos-gnu*)
+ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+@@ -78,13 +78,13 @@
+ fi
+ ;;
+
+-+ *linux-gnueabihf)
+++ riscos-gnu*)
+ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ + ;;
+ +
+-+ *riscos | linux-gnueabihf)
+++ *riscos*)
+ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+@@ -97,7 +97,7 @@
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+-+ linux-gnueabihf)
+++ riscos-gnu*)
+ + # RISC OS
+ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+@@ -110,7 +110,7 @@
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+-+ *linux-gnueabihf)
+++ riscos-gnu*)
+ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+@@ -129,7 +129,7 @@
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+-+ linux-gnueabihf)
+++ riscos-gnu*)
+ + # RISC OS
+ + _LT_TAGVAR(ld_shlibs, $1)=yes
+ + ;;
+@@ -140,7 +140,7 @@
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+-+ *riscos | *linux-gnueabihf)
+++ *riscos*)
+ + _LT_TAGVAR(ld_shlibs, $1)=yes
+ + ;;
+ +
+@@ -151,7 +151,7 @@
+ AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ case $host_os in
+-+ linux-gnueabihf)
+++ riscos-gnu*)
+ + # RISC OS
+ + _LT_TAGVAR(ld_shlibs, $1)=yes
+ + ;;
+@@ -162,7 +162,7 @@
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+-+ *riscos | *linux-gnueabihf)
+++ *riscos*)
+ + _LT_TAGVAR(ld_shlibs, $1)=yes
+ + ;;
+ +
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=d97b2bb44b20de3a...
commit d97b2bb44b20de3a689a88005b24c1102a243b27
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
"Fix" FTBFS: disable maintainer mode for binutils.
Enabling maintainer mode causes bfd-in2.h to be regenerated from
bfd-in.h. This results in the "riscos_module" field in the
elf32_arm_params to be wrapped in #ifdef __RISCOS_TARGET___.
While this is defined when bfd itself is built, it is not defined
when ld is compiled, resulting in a failure to compile
earmelf_riscos_eabi.c (as it expects to be able to address that
parameter.
diff --git a/arm-riscos-gnueabihf/recipes/files/gccsdk/Makefile b/arm-riscos-gnueabihf/recipes/files/gccsdk/Makefile
index ed2283c..5f2740b 100644
--- a/arm-riscos-gnueabihf/recipes/files/gccsdk/Makefile
+++ b/arm-riscos-gnueabihf/recipes/files/gccsdk/Makefile
@@ -75,7 +75,7 @@ GCC_CONFIG_ARGS += --with-pkgversion='GCCSDK GCC $(GCC_VERSION) Release $(GCCSDK
--with-bugurl=http://gccsdk.riscos.info/
BINUTILS_CONFIG_ARGS += --with-pkgversion='GCCSDK GCC $(GCC_VERSION) Release $(GCCSDK_GCC_RISCOS_RELEASE)' \
--with-bugurl=http://gccsdk.riscos.info/
-BINUTILS_CONFIG_ARGS += --enable-maintainer-mode --disable-werror --with-gcc --enable-interwork --disable-nls
+BINUTILS_CONFIG_ARGS += --disable-werror --with-gcc --enable-interwork --disable-nls #--enable-maintainer-mode
# --disable-werror is added because --enable-maintainer-mode turns all warnings into errors and
# the gcc build is not 100% warning free.
# However, this does not help for libstdc++ builds when newlib is used, cfr http://gcc.gnu.org/PR47058.
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=8dda0314c78da253...
commit 8dda0314c78da253226ee3f3c6bae57b4b52068a
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
First cut at GCC 10/arm-riscos-gnueabihf
diff --git a/arm-riscos-gnueabihf/.gitignore b/arm-riscos-gnueabihf/.gitignore
new file mode 100644
index 0000000..e6483c4
--- /dev/null
+++ b/arm-riscos-gnueabihf/.gitignore
@@ -0,0 +1,2 @@
+builddir
+sources
diff --git a/arm-riscos-gnueabihf/Makefile b/arm-riscos-gnueabihf/Makefile
new file mode 100644
index 0000000..0c9eadb
--- /dev/null
+++ b/arm-riscos-gnueabihf/Makefile
@@ -0,0 +1,187 @@
+# Use a tested trunk version of GCCSDK
+UPSTREAM_GCCSDK_VERSION := 7698
+UPSTREAM_GCCSDK_TARBALL := gccsdk$(UPSTREAM_GCCSDK_VERSION).tar.gz
+UPSTREAM_GCCSDK_URI := svn://svn.riscos.info/gccsdk/trunk/autobuilder/develop/gcc@$(UPSTREAM_GCCSDK_VERSION)
+UPSTREAM_GCCSDK_AMP_URI := svn://svn.riscos.info/gccsdk/trunk/gcc4/recipe/patches/automake-for-binutils@$(UPSTREAM_GCCSDK_VERSION)
+UPSTREAM_GCCSDK_LD_URI := svn://svn.riscos.info/gccsdk/trunk/gcc4/riscos/soloader/dynamic/ld.so-1.9.9@$(UPSTREAM_GCCSDK_VERSION)
+UPSTREAM_GCCSDK_SGP_URI := svn://svn.riscos.info/gccsdk/trunk/gcc4/setup-gccsdk-params@$(UPSTREAM_GCCSDK_VERSION)
+UPSTREAM_GCCSDK_UNIXLIB_URI := svn://svn.riscos.info/gccsdk/trunk/gcc4/recipe/files/gcc/libunixlib@$(UPSTREAM_GCCSDK_VERSION)
+
+# OSLib 7.00
+UPSTREAM_OSLIB_VERSION := 700
+UPSTREAM_OSLIB_TARBALL := oslib$(UPSTREAM_OSLIB_VERSION).tar.gz
+UPSTREAM_OSLIB_URI := https://svn.code.sf.net/p/ro-oslib/code/tags/oslib-$(UPSTREAM_OSLIB_VERSI...
+
+# Known tested version of trunk for CCRes
+UPSTREAM_CCRES_VERSION := 96
+UPSTREAM_CCRES_TARBALL := ccres$(UPSTREAM_CCRES_VERSION).tar.gz
+UPSTREAM_CCRES_URI := svn://svn.riscos.info/ccres/trunk@$(UPSTREAM_CCRES_VERSION)
+
+# Makerun
+UPSTREAM_MAKERUN_VERSION := abdbd16
+UPSTREAM_MAKERUN_TARBALL := makerun$(UPSTREAM_MAKERUN_VERSION).tar.gz
+UPSTREAM_MAKERUN_URI := git://git.netsurf-browser.org/makerun.git
+
+# Squeeze
+UPSTREAM_SQUEEZE_VERSION := f26ccd6
+UPSTREAM_SQUEEZE_TARBALL := squeeze$(UPSTREAM_SQUEEZE_VERSION).tar.gz
+UPSTREAM_SQUEEZE_URI := git://git.netsurf-browser.org/squeeze.git
+
+# Infozip
+UPSTREAM_INFOZIP_VERSION := 30
+UPSTREAM_INFOZIP_TARBALL := zip$(UPSTREAM_INFOZIP_VERSION).tar.gz
+UPSTREAM_INFOZIP_URI := https://downloads.sourceforge.net/project/infozip/Zip%203.x%20%28latest%2...
+
+Q ?= @
+TOP := $(CURDIR)
+RECIPES := $(TOP)/recipes
+SOURCESDIR := $(TOP)/sources
+BUILDDIR := $(TOP)/builddir
+BUILDSTEPS := $(BUILDDIR)/build-steps
+
+TARGET_NAME := arm-riscos-gnueabihf
+
+PREFIX ?= /opt/netsurf/$(TARGET_NAME)
+
+# tools
+FETCHSRC:=$(CURDIR)/fetchsrc
+
+.PHONY: all clean distclean
+all: $(BUILDSTEPS)/toolchain.d
+
+clean:
+ rm -fr $(BUILDDIR)
+
+distclean: clean
+ rm -fr $(SOURCESDIR)
+
+###
+# Rules to build the full toolchain
+###
+
+$(BUILDSTEPS)/toolchain.d: $(BUILDSTEPS)/ccres.d $(BUILDSTEPS)/makerun.d $(BUILDSTEPS)/squeeze.d $(BUILDSTEPS)/infozip.d
+ touch $@
+
+###
+# Rules to build and install Infozip
+###
+
+$(BUILDSTEPS)/infozip.d: $(BUILDSTEPS)/gcc.d $(SOURCESDIR)/$(UPSTREAM_INFOZIP_TARBALL)
+ tar -C $(BUILDDIR) -xaf $(SOURCESDIR)/$(UPSTREAM_INFOZIP_TARBALL)
+ for p in `ls $(RECIPES)/patches/infozip/*.p` ; do patch -d $(BUILDDIR)/zip$(UPSTREAM_INFOZIP_VERSION) -p0 <$$p ; done
+ cd $(BUILDDIR)/zip$(UPSTREAM_INFOZIP_VERSION) && make -f unix/Makefile generic LOCAL_ZIP=-DFORRISCOS
+ cp $(BUILDDIR)/zip$(UPSTREAM_INFOZIP_VERSION)/zip $(PREFIX)/cross/bin/zip
+ @# Yuck. Build host tooling should not be installed into the target environment
+ mkdir -p $(PREFIX)/env/bin
+ ln -fs $(PREFIX)/cross/bin/zip $(PREFIX)/env/bin/zip
+ touch $@
+
+###
+# Rules to build and install Makerun
+###
+
+$(BUILDSTEPS)/makerun.d: $(BUILDSTEPS)/gcc.d $(SOURCESDIR)/$(UPSTREAM_MAKERUN_TARBALL)
+ tar -C $(BUILDDIR) -xaf $(SOURCESDIR)/$(UPSTREAM_MAKERUN_TARBALL)
+ cd $(BUILDDIR)/makerun && GCCSDK_INSTALL_CROSSBIN=$(PREFIX)/cross/bin make install
+ touch $@
+
+###
+# Rules to build and install Squeeze
+###
+
+$(BUILDSTEPS)/squeeze.d: $(BUILDSTEPS)/gcc.d $(SOURCESDIR)/$(UPSTREAM_SQUEEZE_TARBALL)
+ tar -C $(BUILDDIR) -xaf $(SOURCESDIR)/$(UPSTREAM_SQUEEZE_TARBALL)
+ cd $(BUILDDIR)/squeeze && GCCSDK_INSTALL_CROSSBIN=$(PREFIX)/cross/bin make install
+ touch $@
+
+###
+# Rules to build and install CCRes
+###
+
+$(BUILDSTEPS)/ccres.d: $(BUILDSTEPS)/oslib.d $(SOURCESDIR)/$(UPSTREAM_CCRES_TARBALL)
+ tar -C $(BUILDDIR) -xaf $(SOURCESDIR)/$(UPSTREAM_CCRES_TARBALL)
+ cd $(BUILDDIR)/ccres && GCCSDK_INSTALL_ENV=$(PREFIX)/env GCCSDK_INSTALL_CROSSBIN=$(PREFIX)/cross/bin make
+ cd $(BUILDDIR)/ccres && GCCSDK_INSTALL_ENV=$(PREFIX)/env GCCSDK_INSTALL_CROSSBIN=$(PREFIX)/cross/bin make install
+ touch $@
+
+###
+# Rules to build and install OSLib
+###
+
+$(BUILDSTEPS)/oslib.d: $(BUILDSTEPS)/gcc.d $(SOURCESDIR)/$(UPSTREAM_OSLIB_TARBALL)
+ tar -C $(BUILDDIR) -xaf $(SOURCESDIR)/$(UPSTREAM_OSLIB_TARBALL)
+ for p in `ls $(RECIPES)/patches/oslib/*.p` ; do patch -d $(BUILDDIR)/oslib -p0 <$$p ; done
+ cd $(BUILDDIR)/oslib && GCCSDK_INSTALL_ENV=$(PREFIX)/env GCCSDK_INSTALL_CROSSBIN=$(PREFIX)/cross/bin make install
+ touch $@
+
+###
+# Rules to build and install GCCSDK
+###
+
+$(BUILDSTEPS)/gcc.d: $(BUILDSTEPS)/gccsdk-srcdir.d
+ cd $(BUILDDIR)/gccsdk && make
+ @# Install empty libraries needed to fool configure scripts
+ for l in c pthread gcc_s ; do $(PREFIX)/cross/bin/$(TARGET_NAME)-ar mv $(PREFIX)/cross/$(TARGET_NAME)/lib/lib$$l.a ; done
+ @# Newer GCCSDK adds these trampoline binaries that for us
+ @# serve no purpose and get in the way.
+ $(RM) $(PREFIX)/cross/bin/$(TARGET_NAME)-gcc-ar $(PREFIX)/cross/bin/$(TARGET_NAME)-gcc-nm $(PREFIX)/cross/bin/$(TARGET_NAME)-gcc-ranlib
+ touch $@
+
+$(BUILDSTEPS)/gccsdk-srcdir.d: $(BUILDSTEPS)/buildsteps.d $(SOURCESDIR)/$(UPSTREAM_GCCSDK_TARBALL)
+ tar -C $(BUILDDIR) -xaf $(SOURCESDIR)/$(UPSTREAM_GCCSDK_TARBALL)
+ cp -p $(RECIPES)/files/gccsdk/gccsdk-params $(BUILDDIR)/gccsdk/gccsdk-params
+ sed -i 's#{PREFIX}#$(PREFIX)#' $(BUILDDIR)/gccsdk/gccsdk-params
+ sed -i \
+ -e "s#GCCSDK_SUPPORTED_GCC_RELEASE=[0-9.]\+#GCCSDK_SUPPORTED_GCC_RELEASE=$$(grep '^GCC_VERSION=[0-9.]\+' $(BUILDDIR)/gccsdk/gcc/setvars | sed -e 's/^GCC_VERSION=//')#" \
+ -e "s#GCCSDK_SUPPORTED_BINUTILS_RELEASE=[0-9.]\+#GCCSDK_SUPPORTED_BINUTILS_RELEASE=$$(grep '^BINUTILS_VERSION=[0-9.]\+' $(BUILDDIR)/gccsdk/gcc/setvars | sed -e 's/^BINUTILS_VERSION=//')#" \
+ $(BUILDDIR)/gccsdk/setup-gccsdk-params
+ cp -p $(RECIPES)/files/gccsdk/Makefile $(BUILDDIR)/gccsdk/Makefile
+ $(Q)for p in $$(ls $(RECIPES)/files/gccsdk/*.p 2>/dev/null) ; do echo " COPY: $$p -> $(BUILDDIR)/gccsdk/gcc/" ; cp -p $$p $(BUILDDIR)/gccsdk/gcc/ ; done
+ $(Q)for p in $$(ls $(RECIPES)/files/gccsdk/*.pp 2>/dev/null) ; do echo " COPY: $$p -> $(BUILDDIR)/gccsdk/gcc/" ; cp -p $$p $(BUILDDIR)/gccsdk/gcc/ ; done
+ $(Q)for p in $$(ls $(RECIPES)/patches/gccsdk/*.p 2>/dev/null) ; do echo "PATCH: $$p" ; patch -d $(BUILDDIR)/gccsdk -p0 <$$p ; done
+ touch $@
+
+###
+# Rules to fetch upstream sources
+###
+
+$(SOURCESDIR)/$(UPSTREAM_GCCSDK_TARBALL):
+ svn export $(UPSTREAM_GCCSDK_URI) $(SOURCESDIR)/gccsdk/gcc
+ svn export $(UPSTREAM_GCCSDK_AMP_URI) $(SOURCESDIR)/gccsdk/automake
+ svn export $(UPSTREAM_GCCSDK_LD_URI) $(SOURCESDIR)/gccsdk/ld
+ svn export $(UPSTREAM_GCCSDK_SGP_URI) $(SOURCESDIR)/gccsdk/
+ svn export $(UPSTREAM_GCCSDK_UNIXLIB_URI) $(SOURCESDIR)/gccsdk/libunixlib
+ tar -C $(SOURCESDIR) -caf $@ gccsdk
+
+$(SOURCESDIR)/$(UPSTREAM_OSLIB_TARBALL):
+ svn co $(UPSTREAM_OSLIB_URI) $(SOURCESDIR)/oslib
+ tar -C $(SOURCESDIR) -caf $@ oslib
+
+$(SOURCESDIR)/$(UPSTREAM_CCRES_TARBALL):
+ svn co $(UPSTREAM_CCRES_URI) $(SOURCESDIR)/ccres
+ tar -C $(SOURCESDIR) -caf $@ ccres
+
+$(SOURCESDIR)/$(UPSTREAM_MAKERUN_TARBALL):
+ $(RM) -rf $(SOURCESDIR)/makerun
+ git clone $(UPSTREAM_MAKERUN_URI) $(SOURCESDIR)/makerun
+ tar -C $(SOURCESDIR) -caf $@ makerun
+
+$(SOURCESDIR)/$(UPSTREAM_SQUEEZE_TARBALL):
+ $(RM) -rf $(SOURCESDIR)/squeeze
+ git clone $(UPSTREAM_SQUEEZE_URI) $(SOURCESDIR)/squeeze
+ tar -C $(SOURCESDIR) -caf $@ squeeze
+
+$(SOURCESDIR)/$(UPSTREAM_INFOZIP_TARBALL):
+ $(FETCHSRC) arm-unknown-riscos $(subst $(SOURCESDIR)/,,$@) $(UPSTREAM_INFOZIP_URI) $@
+
+###
+# Rule to create buildsteps dir
+###
+
+$(BUILDSTEPS)/buildsteps.d: $(SOURCESDIR)
+ mkdir -p $(BUILDSTEPS)
+ touch $@
+
+$(SOURCESDIR):
+ mkdir -p $@
+
diff --git a/arm-riscos-gnueabihf/fetchsrc b/arm-riscos-gnueabihf/fetchsrc
new file mode 100755
index 0000000..92ae5bf
--- /dev/null
+++ b/arm-riscos-gnueabihf/fetchsrc
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+# script to fetch toolchain source tar using ci.netsurf-browser.org as a cache
+
+# Usage fetchsrc <target> <source> <upstream> <output>
+
+NSSRV="https://ci.netsurf-browser.org/toolchain/"
+
+wget -q -O ${4} ${NSSRV}/${1}/${2}
+if [ $? -ne 0 ];then
+ wget -q -O ${4} ${3}
+ if [ $? -ne 0 ];then
+ rm ${4}
+ exit 1
+ fi
+fi
diff --git a/arm-riscos-gnueabihf/recipes/files/gccsdk/Makefile b/arm-riscos-gnueabihf/recipes/files/gccsdk/Makefile
new file mode 100644
index 0000000..ed2283c
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/files/gccsdk/Makefile
@@ -0,0 +1,423 @@
+# To build GCCSDK cross-compiler.
+# Written by John Tytgat / BASS
+# Copyright (c) 2009-2021 GCCSDK Developers
+#
+# Build requirements:
+# - apt-get install flex bison libgmp3-dev libmpfr-dev texinfo build-essential
+# - binutils 2.30 and gcc 10.2 needs automake 1.11.1 and autoconf 2.64 and
+# a recent libtool version.
+# Note the required automake/autoconf/libtool sources will be fetched
+# & built automatically.
+# - gcc 10.2 needs at least GMP 6.1.0, ISL 0.18, MPFR 3.1.4 and MPC 1.0.3 (MPFR needs GMP, MPC needs GMP & MPFR)
+# For MPFR/GMP/ISL/MPC version numbers, a good set can be found mentioned at gcc/contrib/download_prerequisites.
+
+# TARGET can have following values: arm-riscos-gnueabihf
+TARGET=arm-riscos-gnueabihf
+GCC_LANGUAGES="c,c++"
+# Enable shared library support in the cross compiler ?
+CROSS_ENABLE_SHARED=yes
+
+# Release ID for GCCSDK RISC OS release (eg 4.7.4 release 6)
+GCCSDK_GCC_RISCOS_RELEASE=1
+
+# Versions of binutils/autotools needed to build our tools
+AUTOCONF_FOR_BINUTILS_VERSION=2.64
+AUTOMAKE_FOR_BINUTILS_VERSION=1.11.1
+LIBTOOL_FOR_BINUTILS_VERSION=2.4.2
+BINUTILS_VERSION=$(GCCSDK_SUPPORTED_BINUTILS_RELEASE)
+AUTOCONF_FOR_GCC_VERSION=2.69
+AUTOMAKE_FOR_GCC_VERSION=1.15.1
+LIBTOOL_FOR_GCC_VERSION=2.4.2
+
+# Versions of upstream components we need
+# XXX: fetch these ourselves, rather than using download_prerequisites
+GCC_VERSION=$(GCCSDK_SUPPORTED_GCC_RELEASE)
+GMP_VERSION=6.1.0
+ISL_VERSION=0.18
+MPFR_VERSION=3.1.4
+MPC_VERSION=1.1.0
+
+# Whether to enable link-time optimisation
+GCC_USE_LTO=no
+
+# If $(AUTOCONF_AUTOMAKE_LIBTOOL_FOR_BINUTILS_VERSIONS) equals
+# $(AUTOCONF_AUTOMAKE_LIBTOOL_FOR_GCC_VERSIONS) we can reuse the installed
+# buildtools for binutils for building gcc.
+AUTOCONF_AUTOMAKE_LIBTOOL_FOR_BINUTILS_VERSIONS := $(AUTOCONF_FOR_BINUTILS_VERSION)-$(AUTOMAKE_FOR_BINUTILS_VERSION)-$(LIBTOOL_FOR_BINUTILS_VERSION)
+AUTOCONF_AUTOMAKE_LIBTOOL_FOR_GCC_VERSIONS := $(AUTOCONF_FOR_GCC_VERSION)-$(AUTOMAKE_FOR_GCC_VERSION)-$(LIBTOOL_FOR_GCC_VERSION)
+
+# Notes:
+# 1) Configure options are explained at http://gcc.gnu.org/install/configure.html
+# but note that this explanation is for the latest gcc version released and
+# not necessary the gcc version we're building here.
+# Specifying --disable-multilib will significantly reduce build times but then
+# you only end up with UnixLib/softfloat support.
+# Note: --enable-multilib is the default. Don't specify it unless you want to get hit
+# by PR43328/PR45174.
+GCC_CONFIG_ARGS := \
+ --enable-threads=posix \
+ --enable-sjlj-exceptions=no \
+ --enable-c99 \
+ --enable-cmath \
+ --disable-c-mbchar \
+ --disable-wchar_t \
+ --disable-libstdcxx-pch \
+ --disable-tls \
+ --enable-__cxa_atexit \
+ --disable-libssp \
+ --disable-libgomp \
+ --disable-libitm \
+ --with-abi=aapcs-linux \
+ --with-arch=armv4 \
+ --with-float=soft
+BINUTILS_CONFIG_ARGS :=
+GCC_CONFIG_ARGS += --with-pkgversion='GCCSDK GCC $(GCC_VERSION) Release $(GCCSDK_GCC_RISCOS_RELEASE)' \
+ --with-bugurl=http://gccsdk.riscos.info/
+BINUTILS_CONFIG_ARGS += --with-pkgversion='GCCSDK GCC $(GCC_VERSION) Release $(GCCSDK_GCC_RISCOS_RELEASE)' \
+ --with-bugurl=http://gccsdk.riscos.info/
+BINUTILS_CONFIG_ARGS += --enable-maintainer-mode --disable-werror --with-gcc --enable-interwork --disable-nls
+# --disable-werror is added because --enable-maintainer-mode turns all warnings into errors and
+# the gcc build is not 100% warning free.
+# However, this does not help for libstdc++ builds when newlib is used, cfr http://gcc.gnu.org/PR47058.
+GCC_CONFIG_ARGS += --enable-maintainer-mode --disable-werror
+GCC_CONFIG_ARGS += --enable-interwork --disable-nls --disable-libquadmath
+
+# When debugging/testing/validating the compiler add "--enable-checking=all",
+# otherwise add "--enable-checking=release" or even "--enable-checking=no"
+GCC_CONFIG_ARGS += --enable-checking=release
+# Configure args shared between different targets:
+# For debugging:
+# FIXME: add to GCC_BUILD_FLAGS for optimized ARM libraries: CFLAGS_FOR_TARGET="-O3 -march=armv5" CXXFLAGS_FOR_TARGET="-O3 -march=armv5"
+# Or perhaps better, at GCC configure time something like --with-arch=armv6 --with-tune=cortex-a8 --with-float=softfp --with-fpu=vfp ?
+##GCC_BUILD_FLAGS := CFLAGS="-O0 -g" LIBCXXFLAGS="-O0 -g"
+##BINUTILS_BUILD_FLAGS = CFLAGS="-O0 -g"
+
+ROOT := $(CURDIR)
+PREFIX_CROSS := $(GCCSDK_CROSS_PREFIX)
+PREFIX_RONATIVE := $(GCCSDK_RISCOS_PREFIX)/\!GCC
+BUILDDIR := $(GCCSDK_BUILDDIR)
+BUILDSTEPSDIR := buildstepsdir
+# PREFIX_BUILDTOOL_BINUTILS will contain the built autoconf/automake/libtool versions used during building binutils.
+PREFIX_BUILDTOOL_BINUTILS := $(BUILDDIR)/installed-buildtools-for-binutils
+# PREFIX_BUILDTOOL_GCC will contain the built autoconf/automake/libtool versions used during building gcc.
+# When the autoconf/automake/libtool versions needed to build gcc are the same as the autoconf/automake/libtool versions
+# needed to build binutils, PREFIX_BUILDTOOL_GCC will be a symlink to PREFIX_BUILDTOOL_BINUTILS
+# (compare $(AUTOCONF_AUTOMAKE_LIBTOOL_FOR_BINUTILS_VERSIONS) with $(AUTOCONF_AUTOMAKE_LIBTOOL_FOR_GCC_VERSIONS)).
+PREFIX_BUILDTOOL_GCC := $(BUILDDIR)/installed-buildtools-for-gcc
+PREFIX_CROSSGCC_LIBS := $(BUILDDIR)/installed-libs-for-cross-gcc
+SRCDIR := $(GCCSDK_SRCDIR)
+SRCORIGDIR := $(GCCSDK_SRCDIR).orig
+
+ifeq ($(CROSS_ENABLE_SHARED),yes)
+CROSS_GCC_CONFIG_ARGS += target_configargs=--enable-shared=libunixlib,libgcc,libstdc++,libbacktrace
+else
+CROSS_GCC_CONFIG_ARGS += target_configargs=--disable-shared
+endif
+ifeq ($(GCC_USE_LTO),yes)
+CROSS_GCC_CONFIG_ARGS += --enable-lto
+else
+CROSS_GCC_CONFIG_ARGS += --disable-lto
+endif
+
+# Configure arguments Binutils & GCC:
+CROSS_CONFIG_ARGS := --target=$(TARGET) --prefix=$(PREFIX_CROSS)
+
+# To respawn Makefile with setup-gccsdk-param environment loaded.
+GCCSDK_INTERNAL_GETENV=getenv
+ifeq ($(MAKECMDGOALS),)
+MAKECMDGOALS=all
+endif
+
+.NOTPARALLEL:
+.PHONY: all all-done cross clean clean-done clean-cross clean-cross-done distclean distclean-done getenv
+VPATH = $(BUILDSTEPSDIR)
+
+# Default target is to build the cross-compiler (including the RISC OS tools):
+all: $(GCCSDK_INTERNAL_GETENV)
+all-done: cross-done
+
+# Builds the cross compiler:
+cross: $(GCCSDK_INTERNAL_GETENV)
+cross-done: cross-gcc-built cross-riscostools-built
+ touch $(BUILDSTEPSDIR)/$@
+
+clean: $(GCCSDK_INTERNAL_GETENV)
+clean-done:
+ -rm -rf $(BUILDDIR) $(BUILDSTEPSDIR) $(SRCDIR) $(GCCSDK_CROSS_PREFIX)
+
+# Return to a state for doing a full fresh cross build (using the current binutils/gcc sources).
+clean-cross: $(GCCSDK_INTERNAL_GETENV)
+clean-cross-done:
+ -rm -rf $(BUILDSTEPSDIR)/cross-* $(BUILDDIR)/cross* $(GCCSDK_CROSS_PREFIX)
+
+distclean: $(GCCSDK_INTERNAL_GETENV)
+distclean-done: clean-done
+ -rm -rf release-area $(SRCORIGDIR)
+
+# Respawn Makefile again after having loaded all our GCCSDK environment variables.
+ifeq ($(GCCSDK_INTERNAL_GETENV),getenv)
+getenv:
+ test -d $(BUILDSTEPSDIR) || mkdir $(BUILDSTEPSDIR)
+ @bash -c ". ./setup-gccsdk-params && $(MAKE) $(patsubst %,%-done,$(MAKECMDGOALS)) GCCSDK_INTERNAL_GETENV="
+endif
+
+# -- Configure & building:
+
+# Configure & build autoconf-for-binutils tool:
+buildtool-autoconf-for-binutils-built: src-autoconf-for-binutils-copied
+ -rm -rf $(BUILDDIR)/buildtool-autoconf-for-binutils
+ mkdir -p $(BUILDDIR)/buildtool-autoconf-for-binutils
+ cd $(BUILDDIR)/buildtool-autoconf-for-binutils && $(SRCDIR)/autoconf-for-binutils/configure --prefix=$(PREFIX_BUILDTOOL_BINUTILS) && $(MAKE) && $(MAKE) install
+ touch $(BUILDSTEPSDIR)/$@
+
+ifneq ($(AUTOCONF_AUTOMAKE_LIBTOOL_FOR_BINUTILS_VERSIONS),$(AUTOCONF_AUTOMAKE_LIBTOOL_FOR_GCC_VERSIONS))
+# Configure & build autoconf-for-gcc tool:
+buildtool-autoconf-for-gcc-built: src-autoconf-for-gcc-copied
+ -rm -rf $(BUILDDIR)/buildtool-autoconf-for-gcc
+ mkdir -p $(BUILDDIR)/buildtool-autoconf-for-gcc
+ cd $(BUILDDIR)/buildtool-autoconf-for-gcc && $(SRCDIR)/autoconf-for-gcc/configure --prefix=$(PREFIX_BUILDTOOL_GCC) && $(MAKE) && $(MAKE) install
+else
+# autoconf-for-gcc, automake-for-gcc and libtool-for-gcc are the same as autoconf-for-binutils, automake-for-binutils and libtool-for-binutils so we can use PREFIX_BUILDTOOL_GCC as PREFIX_BUILDTOOL_BINUTILS
+buildtool-autoconf-for-gcc-built: buildtool-autoconf-for-binutils-built
+ ln -f -s $(PREFIX_BUILDTOOL_BINUTILS) $(PREFIX_BUILDTOOL_GCC)
+endif
+ touch $(BUILDSTEPSDIR)/$@
+
+# Configure & build automake-for-binutils tool:
+buildtool-automake-for-binutils-built: src-automake-for-binutils-copied buildtool-autoconf-for-binutils-built
+ -rm -rf $(BUILDDIR)/buildtool-automake-for-binutils
+ mkdir -p $(BUILDDIR)/buildtool-automake-for-binutils
+ cd $(BUILDDIR)/buildtool-automake-for-binutils && PATH="$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" && $(SRCDIR)/automake-for-binutils/configure --prefix=$(PREFIX_BUILDTOOL_BINUTILS) && $(MAKE) && $(MAKE) install
+ touch $(BUILDSTEPSDIR)/$@
+
+ifneq ($(AUTOCONF_AUTOMAKE_LIBTOOL_FOR_BINUTILS_VERSIONS),$(AUTOCONF_AUTOMAKE_LIBTOOL_FOR_GCC_VERSIONS))
+# Configure & build automake-for-gcc tool:
+buildtool-automake-for-gcc-built: src-automake-for-gcc-copied buildtool-autoconf-for-gcc-built
+ -rm -rf $(BUILDDIR)/buildtool-automake-for-gcc
+ mkdir -p $(BUILDDIR)/buildtool-automake-for-gcc
+ cd $(BUILDDIR)/buildtool-automake-for-gcc && PATH="$(PREFIX_BUILDTOOL_GCC)/bin:$(PATH)" && $(SRCDIR)/automake-for-gcc/configure --prefix=$(PREFIX_BUILDTOOL_GCC) && $(MAKE) && $(MAKE) install
+else
+# autoconf-for-gcc, automake-for-gcc and libtool-for-gcc are the same as autoconf-for-binutils, automake-for-binutils and libtool-for-binutils so we can use PREFIX_BUILDTOOL_GCC as PREFIX_BUILDTOOL_BINUTILS
+buildtool-automake-for-gcc-built: buildtool-automake-for-binutils-built
+endif
+ touch $(BUILDSTEPSDIR)/$@
+
+# Configure & build libtool-for-binutils tool:
+buildtool-libtool-for-binutils-built: src-libtool-for-binutils-copied buildtool-autoconf-for-binutils-built buildtool-automake-for-binutils-built
+ -rm -rf $(BUILDDIR)/buildtool-libtool-for-binutils
+ mkdir -p $(BUILDDIR)/buildtool-libtool-for-binutils
+ cd $(BUILDDIR)/buildtool-libtool-for-binutils && PATH="$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" && $(SRCDIR)/libtool-for-binutils/configure --prefix=$(PREFIX_BUILDTOOL_BINUTILS) && $(MAKE) && $(MAKE) install
+ touch $(BUILDSTEPSDIR)/$@
+
+ifneq ($(AUTOCONF_AUTOMAKE_LIBTOOL_FOR_BINUTILS_VERSIONS),$(AUTOCONF_AUTOMAKE_LIBTOOL_FOR_GCC_VERSIONS))
+# Configure & build libtool-for-gcc tool:
+buildtool-libtool-for-gcc-built: src-libtool-for-gcc-copied buildtool-autoconf-for-gcc-built buildtool-automake-for-gcc-built
+ -rm -rf $(BUILDDIR)/buildtool-libtool-for-gcc
+ mkdir -p $(BUILDDIR)/buildtool-libtool-for-gcc
+ cd $(BUILDDIR)/buildtool-libtool-for-gcc && PATH="$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" && $(SRCDIR)/libtool-for-gcc/configure --prefix=$(PREFIX_BUILDTOOL_GCC) && $(MAKE) && $(MAKE) install
+else
+# autoconf-for-gcc, automake-for-gcc and libtool-for-gcc are the same as autoconf-for-binutils, automake-for-binutils and libtool-for-binutils so we can use PREFIX_BUILDTOOL_GCC as PREFIX_BUILDTOOL_BINUTILS
+buildtool-libtool-for-gcc-built: buildtool-libtool-for-binutils-built
+endif
+ touch $(BUILDSTEPSDIR)/$@
+
+# Configure binutils cross:
+cross-binutils-configured: src-binutils-copied
+ -rm -rf $(BUILDDIR)/cross-binutils
+ mkdir -p $(BUILDDIR)/cross-binutils
+ cd $(BUILDDIR)/cross-binutils && PATH="$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" && $(SRCDIR)/binutils/configure $(CROSS_CONFIG_ARGS) $(BINUTILS_CONFIG_ARGS)
+ touch $(BUILDSTEPSDIR)/$@
+
+# Build binutils cross:
+cross-binutils-built: cross-binutils-configured
+ cd $(BUILDDIR)/cross-binutils && PATH="$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" && $(SRCDIR)/binutils/configure $(CROSS_CONFIG_ARGS) $(BINUTILS_CONFIG_ARGS) && $(MAKE) $(BINUTILS_BUILD_FLAGS) && $(MAKE) install
+ touch $(BUILDSTEPSDIR)/$@
+
+# Configure gcc cross:
+cross-gcc-configured: src-gcc-copied cross-binutils-built
+ -rm -rf $(BUILDDIR)/cross-gcc
+ mkdir -p $(BUILDDIR)/cross-gcc
+ mkdir -p $(PREFIX_CROSS)/$(TARGET)/lib
+ for l in c pthread gcc_s; do $(PREFIX_CROSS)/bin/$(TARGET)-ar mv $(PREFIX_CROSS)/$(TARGET)/lib/lib$${l}.a; done
+ cd $(BUILDDIR)/cross-gcc && PATH="$(PREFIX_BUILDTOOL_GCC)/bin:$(PREFIX_CROSS)/bin:$(PATH)" && $(SRCDIR)/gcc/configure $(CROSS_CONFIG_ARGS) $(CROSS_GCC_CONFIG_ARGS) $(GCC_CONFIG_ARGS) --enable-languages=$(GCC_LANGUAGES)
+ touch $(BUILDSTEPSDIR)/$@
+
+# Build gcc cross:
+cross-gcc-built: cross-gcc-configured
+ cd $(BUILDDIR)/cross-gcc && PATH="$(PREFIX_BUILDTOOL_GCC)/bin:$(PREFIX_CROSS)/bin:$(PATH)" && $(MAKE) $(GCC_BUILD_FLAGS) && $(MAKE) install
+ touch $(BUILDSTEPSDIR)/$@
+
+# Build the RISC OS related tools (cmunge, elf2aif, asasm, etc) cross:
+# XXX: currently, this just builds ld -- what more do we need?
+cross-riscostools-built: cross-gcc-built
+ -rm -rf $(BUILDDIR)/cross-ld
+ mkdir -p $(BUILDDIR)/cross-ld
+ cd $(ROOT)/ld && PATH="$(PREFIX_CROSS)/bin:$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" autoreconf --install
+ cd $(BUILDDIR)/cross-ld && PATH="$(PREFIX_CROSS)/bin:$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" CC=$(GCCSDK_INSTALL_CROSSBIN)/$(TARGET)-gcc $(ROOT)/ld/configure --prefix=$(PREFIX_CROSS)/$(TARGET) --host=$(TARGET) --target=$(TARGET)
+ cd $(BUILDDIR)/cross-ld && PATH="$(PREFIX_CROSS)/bin:$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" make install
+ touch $(BUILDSTEPSDIR)/$@
+
+# -- Source unpacking.
+
+# Unpack & copy autoconf-for-binutils source:
+src-autoconf-for-binutils-copied: $(SRCORIGDIR)/autoconf-$(AUTOCONF_FOR_BINUTILS_VERSION).tar.xz
+ -rm -rf $(SRCORIGDIR)/autoconf-$(AUTOCONF_FOR_BINUTILS_VERSION) $(SRCDIR)/autoconf-for-binutils
+ cd $(SRCORIGDIR) && tar xf $<
+ -mkdir -p $(SRCDIR)/autoconf-for-binutils
+ cp -T -p -r $(SRCORIGDIR)/autoconf-$(AUTOCONF_FOR_BINUTILS_VERSION) $(SRCDIR)/autoconf-for-binutils
+ touch $(BUILDSTEPSDIR)/$@
+
+ifneq ($(AUTOCONF_AUTOMAKE_LIBTOOL_FOR_BINUTILS_VERSIONS),$(AUTOCONF_AUTOMAKE_LIBTOOL_FOR_GCC_VERSIONS))
+# Unpack & copy autoconf-for-gcc source:
+src-autoconf-for-gcc-copied: $(SRCORIGDIR)/autoconf-$(AUTOCONF_FOR_GCC_VERSION).tar.xz
+ -rm -rf $(SRCORIGDIR)/autoconf-$(AUTOCONF_FOR_GCC_VERSION) $(SRCDIR)/autoconf-for-gcc
+ cd $(SRCORIGDIR) && tar xf $<
+ -mkdir -p $(SRCDIR)/autoconf-for-gcc
+ cp -T -p -r $(SRCORIGDIR)/autoconf-$(AUTOCONF_FOR_GCC_VERSION) $(SRCDIR)/autoconf-for-gcc
+ touch $(BUILDSTEPSDIR)/$@
+endif
+
+# Unpack & copy automake-for-binutils source:
+src-automake-for-binutils-copied: $(SRCORIGDIR)/automake-$(AUTOMAKE_FOR_BINUTILS_VERSION).tar.bz2
+ -rm -rf $(SRCORIGDIR)/automake-$(AUTOMAKE_FOR_BINUTILS_VERSION) $(SRCDIR)/automake-for-binutils
+ cd $(SRCORIGDIR) && tar xf $<
+ -mkdir -p $(SRCDIR)/automake-for-binutils
+ cp -T -p -r $(SRCORIGDIR)/automake-$(AUTOMAKE_FOR_BINUTILS_VERSION) $(SRCDIR)/automake-for-binutils
+ for p in $$(ls $(ROOT)/automake/*.p); do patch -d $(SRCDIR)/automake-for-binutils -p0 -l < $$p; done
+ touch $(BUILDSTEPSDIR)/$@
+
+ifneq ($(AUTOCONF_AUTOMAKE_LIBTOOL_FOR_BINUTILS_VERSIONS),$(AUTOCONF_AUTOMAKE_LIBTOOL_FOR_GCC_VERSIONS))
+# Unpack & copy automake-for-gcc source:
+src-automake-for-gcc-copied: $(SRCORIGDIR)/automake-$(AUTOMAKE_FOR_GCC_VERSION).tar.xz
+ -rm -rf $(SRCORIGDIR)/automake-$(AUTOMAKE_FOR_GCC_VERSION) $(SRCDIR)/automake-for-gcc
+ cd $(SRCORIGDIR) && tar xf $<
+ -mkdir -p $(SRCDIR)/automake-for-gcc
+ cp -T -p -r $(SRCORIGDIR)/automake-$(AUTOMAKE_FOR_GCC_VERSION) $(SRCDIR)/automake-for-gcc
+ touch $(BUILDSTEPSDIR)/$@
+endif
+
+# Unpack & copy libtool-for-binutils source:
+src-libtool-for-binutils-copied: $(SRCORIGDIR)/libtool-$(LIBTOOL_FOR_BINUTILS_VERSION).tar.gz
+ -rm -rf $(SRCORIGDIR)/libtool-$(LIBTOOL_FOR_BINUTILS_VERSION) $(SRCDIR)/libtool-for-binutils
+ cd $(SRCORIGDIR) && tar xf $<
+ -mkdir -p $(SRCDIR)/libtool-for-binutils
+ cp -T -p -r $(SRCORIGDIR)/libtool-$(LIBTOOL_FOR_BINUTILS_VERSION) $(SRCDIR)/libtool-for-binutils
+ touch $(BUILDSTEPSDIR)/$@
+
+ifneq ($(AUTOCONF_AUTOMAKE_LIBTOOL_FOR_BINUTILS_VERSIONS),$(AUTOCONF_AUTOMAKE_LIBTOOL_FOR_GCC_VERSIONS))
+# Unpack & copy libtool-for-gcc source:
+src-libtool-for-gcc-copied: $(SRCORIGDIR)/libtool-$(LIBTOOL_FOR_GCC_VERSION).tar.gz
+ -rm -rf $(SRCORIGDIR)/libtool-$(LIBTOOL_FOR_GCC_VERSION) $(SRCDIR)/libtool-for-gcc
+ cd $(SRCORIGDIR) && tar xf $<
+ -mkdir -p $(SRCDIR)/libtool-for-gcc
+ cp -T -p -r $(SRCORIGDIR)/libtool-$(LIBTOOL_FOR_GCC_VERSION) $(SRCDIR)/libtool-for-gcc
+ touch $(BUILDSTEPSDIR)/$@
+endif
+
+# Unpack & copy (and optionally patch) binutils source:
+# As we're patching and (re)configuring, we need built & installed versions of
+# autoconf, automake and libtool.
+src-binutils-copied: $(SRCORIGDIR)/binutils-$(BINUTILS_VERSION).tar.bz2 buildtool-autoconf-for-binutils-built buildtool-automake-for-binutils-built buildtool-libtool-for-binutils-built
+ -rm -rf $(SRCORIGDIR)/binutils-$(BINUTILS_VERSION) $(SRCDIR)/binutils
+ cd $(SRCORIGDIR) && tar xf $<
+ -mkdir -p $(SRCDIR)/binutils
+ cp -T -p -r $(SRCORIGDIR)/binutils-$(BINUTILS_VERSION) $(SRCDIR)/binutils
+ cp $(ROOT)/gcc/ld.emulparams.armelf_riscos_eabi.sh $(SRCDIR)/binutils/ld/emulparams/armelf_riscos_eabi.sh
+ cp $(ROOT)/gcc/gas.config.te-riscos.h $(SRCDIR)/binutils/gas/config/te-riscos.h
+ for p in $$(ls $(ROOT)/gcc/*.pp); do patch -d $(SRCDIR)/binutils -p0 -l < $$p ; done
+ cd $(SRCDIR)/binutils/ld && PATH="$(PREFIX_BUILDTOOL_BINUTILS)/bin:$(PATH)" autoreconf
+ touch $(BUILDSTEPSDIR)/$@
+
+# Unpack & copy or checkout the gcc source:
+# As we're patching and (re)configuring, we need built & installed versions of
+# autoconf, automake and libtool.
+src-gcc-copied: buildtool-autoconf-for-gcc-built buildtool-automake-for-gcc-built buildtool-libtool-for-gcc-built
+src-gcc-copied: $(SRCORIGDIR)/gcc-$(GCC_VERSION).tar.xz
+ -rm -rf $(SRCORIGDIR)/gcc-$(GCC_VERSION) $(SRCDIR)/gcc
+ cd $(SRCORIGDIR) && tar xf $<
+ -mkdir -p $(SRCDIR)/gcc
+ cp -T -p -r $(SRCORIGDIR)/gcc-$(GCC_VERSION) $(SRCDIR)/gcc
+ mkdir -p $(SRCDIR)/gcc/libstdc++-v3/config/os/riscos
+ cp -T -p $(ROOT)/gcc//gcc.config.arm.riscos-elf.h $(SRCDIR)/gcc/gcc/config/arm/riscos-elf.h
+ cp -T -p $(ROOT)/gcc/gcc.config.arm.riscos-gnueabihf.h $(SRCDIR)/gcc/gcc/config/arm/riscos-gnueabihf.h
+ cp -T -p $(ROOT)/gcc/gcc.config.arm.riscos-gcc.c $(SRCDIR)/gcc/gcc/config/arm/riscos-gcc.c
+ cp -T -p $(ROOT)/gcc/gcc.config.arm.riscos.c $(SRCDIR)/gcc/gcc/config/arm/riscos.c
+ cp -T -p $(ROOT)/gcc/gcc.config.arm.riscos.md $(SRCDIR)/gcc/gcc/config/arm/riscos.md
+ cp -T -p $(ROOT)/gcc/gcc.config.arm.riscos.opt $(SRCDIR)/gcc/gcc/config/arm/riscos.opt
+ cp -T -p $(ROOT)/gcc/gcc.config.arm.t-arm-riscos-elf $(SRCDIR)/gcc/gcc/config/arm/t-arm-riscos-elf
+ cp -T -p $(ROOT)/gcc/gcc.config.arm.t-riscos-gnueabihf $(SRCDIR)/gcc/gcc/config/arm/t-riscos-gnueabihf
+ cp -T -p $(ROOT)/gcc/gcc.config.arm.xm-riscos.h $(SRCDIR)/gcc/gcc/config/arm/xm-riscos.h
+ cp -T -p $(ROOT)/gcc/libgcc.config.arm.t-arm-riscos-elf $(SRCDIR)/gcc/libgcc/config/arm/t-arm-riscos-elf
+ cp -T -p $(ROOT)/gcc/libgcc.config.arm.t-riscos-gnueabihf $(SRCDIR)/gcc/libgcc/config/arm/t-riscos-gnueabihf
+ cp -T -p $(ROOT)/gcc/libstdc++-v3.config.os.riscos.ctype_base.h $(SRCDIR)/gcc/libstdc++-v3/config/os/riscos/ctype_base.h
+ cp -T -p $(ROOT)/gcc/libstdc++-v3.config.os.riscos.ctype_configure_char.cc $(SRCDIR)/gcc/libstdc++-v3/config/os/riscos/ctype_configure_char.cc
+ cp -T -p $(ROOT)/gcc/libstdc++-v3.config.os.riscos.ctype_inline.h $(SRCDIR)/gcc/libstdc++-v3/config/os/riscos/ctype_inline.h
+ cp -T -p $(ROOT)/gcc/libstdc++-v3.config.os.riscos.error_constants.h $(SRCDIR)/gcc/libstdc++-v3/config/os/riscos/error_constants.h
+ cp -T -p $(ROOT)/gcc/libstdc++-v3.config.os.riscos.os_defines.h $(SRCDIR)/gcc/libstdc++-v3/config/os/riscos/os_defines.h
+ for p in $$(ls $(ROOT)/gcc/*.p); do patch -d $(SRCDIR)/gcc -p0 -l < $$p ; done
+ cp -T -p -r $(ROOT)/libunixlib $(SRCDIR)/gcc/libunixlib
+ cd $(SRCDIR)/gcc && $(SRCDIR)/gcc/contrib/download_prerequisites
+ cd $(SRCDIR)/gcc && PATH="$(PREFIX_BUILDTOOL_GCC)/bin:$(PATH)" autogen Makefile.def
+ cd $(SRCDIR)/gcc && PATH="$(PREFIX_BUILDTOOL_GCC)/bin:$(PATH)" autoconf
+ cd $(SRCDIR)/gcc/libcpp && PATH="$(PREFIX_BUILDTOOL_GCC)/bin:$(PATH)" ACLOCAL="aclocal -I .. -I ../config" autoreconf -v
+ cd $(SRCDIR)/gcc/libiberty && PATH="$(PREFIX_BUILDTOOL_GCC)/bin:$(PATH)" ACLOCAL="aclocal -I .. -I ../config" autoreconf -v
+ cd $(SRCDIR)/gcc/libstdc++-v3 && PATH="$(PREFIX_BUILDTOOL_GCC)/bin:$(PATH)" ACLOCAL="aclocal -I .. -I ../config" autoreconf -v
+ cd $(SRCDIR)/gcc && PATH="$(PREFIX_BUILDTOOL_GCC)/bin:$(PATH)" $(SRCDIR)/gcc/libunixlib/gen-auto.pl
+ cd $(SRCDIR)/gcc/libunixlib && PATH="$(PREFIX_BUILDTOOL_GCC)/bin:$(PATH)" ACLOCAL="aclocal -I .. -I ../config" autoreconf -v
+ touch $(BUILDSTEPSDIR)/$@
+
+# -- Source downloading.
+
+# Download autoconf source to be used to build binutils:
+$(SRCORIGDIR)/autoconf-$(AUTOCONF_FOR_BINUTILS_VERSION).tar.xz:
+ -mkdir -p $(SRCORIGDIR)
+ cd $(SRCORIGDIR) && wget -c https://ftpmirror.gnu.org/autoconf/autoconf-$(AUTOCONF_FOR_BINUTILS_VERSI...
+ touch $@
+
+# Download automake source to be used to build binutils/autoconf-for-binutils:
+$(SRCORIGDIR)/automake-$(AUTOMAKE_FOR_BINUTILS_VERSION).tar.bz2:
+ -mkdir -p $(SRCORIGDIR)
+ cd $(SRCORIGDIR) && wget -c https://ftpmirror.gnu.org/automake/automake-$(AUTOMAKE_FOR_BINUTILS_VERSI...
+ touch $@
+
+# Download libtool source to be used to build binutils/autoconf-for-binutils:
+$(SRCORIGDIR)/libtool-$(LIBTOOL_FOR_BINUTILS_VERSION).tar.gz:
+ -mkdir -p $(SRCORIGDIR)
+ cd $(SRCORIGDIR) && wget -c https://ftpmirror.gnu.org/libtool/libtool-$(LIBTOOL_FOR_BINUTILS_VERSION)...
+ touch $@
+
+ifneq ($(AUTOCONF_FOR_BINUTILS_VERSION),$(AUTOCONF_FOR_GCC_VERSION))
+# Download autoconf source to be used to build gcc:
+$(SRCORIGDIR)/autoconf-$(AUTOCONF_FOR_GCC_VERSION).tar.xz:
+ -mkdir -p $(SRCORIGDIR)
+ cd $(SRCORIGDIR) && wget -c https://ftpmirror.gnu.org/autoconf/autoconf-$(AUTOCONF_FOR_GCC_VERSION).t...
+ touch $@
+endif
+
+ifneq ($(AUTOMAKE_FOR_BINUTILS_VERSION),$(AUTOMAKE_FOR_GCC_VERSION))
+# Download automake source to be used to build gcc:
+$(SRCORIGDIR)/automake-$(AUTOMAKE_FOR_GCC_VERSION).tar.xz:
+ -mkdir -p $(SRCORIGDIR)
+ cd $(SRCORIGDIR) && wget -c https://ftpmirror.gnu.org/automake/automake-$(AUTOMAKE_FOR_GCC_VERSION).t...
+ touch $@
+endif
+
+ifneq ($(LIBTOOL_FOR_BINUTILS_VERSION),$(LIBTOOL_FOR_GCC_VERSION))
+# Download libtool source to be used to build gcc:
+$(SRCORIGDIR)/libtool-$(LIBTOOL_FOR_GCC_VERSION).tar.gz:
+ -mkdir -p $(SRCORIGDIR)
+ cd $(SRCORIGDIR) && wget -c https://ftpmirror.gnu.org/libtool/libtool-$(LIBTOOL_FOR_GCC_VERSION).tar.gz
+ touch $@
+endif
+
+# Download binutils source:
+$(SRCORIGDIR)/binutils-$(BINUTILS_VERSION).tar.bz2:
+ -mkdir -p $(SRCORIGDIR)
+ cd $(SRCORIGDIR) && wget -c https://ftpmirror.gnu.org/binutils/binutils-$(BINUTILS_VERSION).tar.bz2
+ touch $@
+
+# Download gcc source:
+$(SRCORIGDIR)/gcc-$(GCC_VERSION).tar.xz:
+ -mkdir -p $(SRCORIGDIR)
+ cd $(SRCORIGDIR) && wget -c https://ftpmirror.gnu.org/gcc/gcc-$(GCC_VERSION)/gcc-$(GCC_VERSION).tar.xz
+ touch $@
diff --git a/arm-riscos-gnueabihf/recipes/files/gccsdk/gccsdk-params b/arm-riscos-gnueabihf/recipes/files/gccsdk/gccsdk-params
new file mode 100644
index 0000000..4f48c3c
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/files/gccsdk/gccsdk-params
@@ -0,0 +1,8 @@
+# -- Following section is user configurable:
+# This is where the cross compiler will be installed. It needs to end in 'bin'.
+export GCCSDK_INSTALL_CROSSBIN={PREFIX}/cross/bin
+# This is where the porting tools and any libraries you build will be installed.
+export GCCSDK_INSTALL_ENV={PREFIX}/env
+
+# -- Do not change following section:
+
diff --git a/arm-riscos-gnueabihf/recipes/patches/gccsdk/posix-extended-locale.p b/arm-riscos-gnueabihf/recipes/patches/gccsdk/posix-extended-locale.p
new file mode 100644
index 0000000..e422786
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/patches/gccsdk/posix-extended-locale.p
@@ -0,0 +1,1920 @@
+Index: libunixlib/Makefile.am
+===================================================================
+--- libunixlib/Makefile.am (revision 7698)
++++ libunixlib/Makefile.am (working copy)
+@@ -583,11 +583,11 @@
+ else
+ locale_src = \
+ locale/localeconv.c \
++ locale/newlocale.c \
+ locale/nl_langinfo.c \
+ locale/setlocale.c \
+ locale/strcoll.c \
+- locale/strxfrm.c \
+- locale/territory.c
++ locale/strxfrm.c
+ endif
+ locale_src += \
+ locale/iconv.c
+@@ -1312,6 +1312,7 @@
+ bits/in.h \
+ bits/libc-lock.h \
+ bits/locale.h \
++ bits/locale_t.h \
+ bits/mathcalls.h \
+ bits/mathdef.h \
+ bits/mathinline.h \
+Index: libunixlib/ctype/ctypetable.c
+===================================================================
+--- libunixlib/ctype/ctypetable.c (revision 7698)
++++ libunixlib/ctype/ctypetable.c (working copy)
+@@ -10,36 +10,35 @@
+ #include <internal/os.h>
+ #include <internal/unix.h>
+
+-/* Note the offset 1 and depth 257 instead of 0 and 256: ISO C says we must
+- support EOF. */
+-static unsigned char ctype[257];
+-const unsigned char * const __ctype = &ctype[1];
++/* Global containing current locale settings. */
++struct _locale __locale_global;
++/* Offset 1 as the first entry is reserved for EOF. */
++const unsigned char * const __ctype = &__locale_global.ctype[1];
++const short * const __ctype_upper = &__locale_global.ctype_upper[1];
++const short * const __ctype_lower = &__locale_global.ctype_lower[1];
+
+-static short ctype_upper[257];
+-const short * const __ctype_upper = &ctype_upper[1];
+-
+-static short ctype_lower[257];
+-const short * const __ctype_lower = &ctype_lower[1];
+-
+ void
+-__build_ctype_tables (int territory)
++__build_ctype_tables (locale_t locobj, int territory)
+ {
+ PTHREAD_UNSAFE
+
+ if (territory == -2)
+ {
+- /* Initialise the array. This is only done by __unixinit(). */
++ /* Initialise the array. This is only done by __unixinit()/newlocale(). */
+ territory = -1;
+- for (int x = 0; x <= LC_ALL; x++)
+- __locale_territory[x] = -1;
++ for (int x = 0; x < LC_ALL; x++)
++ locobj->locale_territory[x] = -1;
++ __localeconv_lconv_init(&locobj->lc);
++ locobj->lc_needs_refresh = 1;
+ }
+
+ /* Initialise ctype_upper/ctype_lower tables. */
+ for (int x = 0; x < 257; x++)
+ {
+- /* In the C/POSIX locate, tolower(top bit set char)
++ /* In the C/POSIX locale, tolower(top bit set char)
+ should return the character unchanged. */
+- ctype_lower[x] = ctype_upper[x] = x - 1;
++ locobj->ctype_lower[x] = locobj->ctype_upper[x] = x - 1;
++ locobj->ctype[x] = 0;
+ }
+
+ int regs[10];
+@@ -61,7 +60,7 @@
+ for (int offset = 1; bits; bits = bits >> 1, offset += 1)
+ {
+ if (bits & 1)
+- ctype[pos + offset] |= 1 << code;
++ locobj->ctype[pos + offset] |= 1 << code;
+ }
+ pos += 32;
+ }
+@@ -80,7 +79,7 @@
+ int y = (territory == -1) ? 128 : 256;
+ for (int x = 1; x <= y; x++)
+ {
+- ctype_lower[x] = (short)*p++;
+- ctype_upper[x] = (short)*q++;
++ locobj->ctype_lower[x] = (short)*p++;
++ locobj->ctype_upper[x] = (short)*q++;
+ }
+ }
+Index: libunixlib/ctype/isalnum.c
+===================================================================
+--- libunixlib/ctype/isalnum.c (revision 7698)
++++ libunixlib/ctype/isalnum.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (isalnum) (int c)
+@@ -10,3 +11,8 @@
+ return isalnum (c);
+ }
+
++int
++isalnum_l (int c, locale_t locobj)
++{
++ return ((&locobj->ctype[1])[c] & (___ctype_alpha | ___ctype_digit));
++}
+Index: libunixlib/ctype/isalpha.c
+===================================================================
+--- libunixlib/ctype/isalpha.c (revision 7698)
++++ libunixlib/ctype/isalpha.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (isalpha) (int c)
+@@ -10,3 +11,8 @@
+ return isalpha (c);
+ }
+
++int
++isalpha_l (int c, locale_t locobj)
++{
++ return ((&locobj->ctype[1])[c] & ___ctype_alpha);
++}
+Index: libunixlib/ctype/isascii.c
+===================================================================
+--- libunixlib/ctype/isascii.c (revision 7698)
++++ libunixlib/ctype/isascii.c (working copy)
+@@ -10,3 +10,9 @@
+ return isascii (c);
+ }
+
++int
++isascii_l (int c, locale_t locobj)
++{
++ (void) locobj;
++ return isascii (c);
++}
+Index: libunixlib/ctype/isblank.c
+===================================================================
+--- libunixlib/ctype/isblank.c (revision 7698)
++++ libunixlib/ctype/isblank.c (working copy)
+@@ -9,3 +9,10 @@
+ {
+ return isblank (c);
+ }
++
++int
++isblank_l (int c, locale_t locobj)
++{
++ (void) locobj;
++ return isblank (c);
++}
+Index: libunixlib/ctype/iscntrl.c
+===================================================================
+--- libunixlib/ctype/iscntrl.c (revision 7698)
++++ libunixlib/ctype/iscntrl.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (iscntrl) (int c)
+@@ -10,3 +11,8 @@
+ return iscntrl (c);
+ }
+
++int
++iscntrl_l (int c, locale_t locobj)
++{
++ return ((&locobj->ctype[1])[c] & ___ctype_ctrl);
++}
+Index: libunixlib/ctype/isdigit.c
+===================================================================
+--- libunixlib/ctype/isdigit.c (revision 7698)
++++ libunixlib/ctype/isdigit.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (isdigit) (int c)
+@@ -10,3 +11,8 @@
+ return isdigit (c);
+ }
+
++int
++isdigit_l (int c, locale_t locobj)
++{
++ return ((&locobj->ctype[1])[c] & ___ctype_digit);
++}
+Index: libunixlib/ctype/isgraph.c
+===================================================================
+--- libunixlib/ctype/isgraph.c (revision 7698)
++++ libunixlib/ctype/isgraph.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (isgraph) (int c)
+@@ -10,3 +11,8 @@
+ return isgraph (c);
+ }
+
++int
++isgraph_l (int c, locale_t locobj)
++{
++ return ((&locobj->ctype[1])[c] & ~(___ctype_white | ___ctype_ctrl));
++}
+Index: libunixlib/ctype/islower.c
+===================================================================
+--- libunixlib/ctype/islower.c (revision 7698)
++++ libunixlib/ctype/islower.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (islower) (int c)
+@@ -10,3 +11,8 @@
+ return islower (c);
+ }
+
++int
++islower_l (int c, locale_t locobj)
++{
++ return ((&locobj->ctype[1])[c] & ___ctype_lower);
++}
+Index: libunixlib/ctype/isprint.c
+===================================================================
+--- libunixlib/ctype/isprint.c (revision 7698)
++++ libunixlib/ctype/isprint.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (isprint) (int c)
+@@ -10,3 +11,10 @@
+ return isprint (c);
+ }
+
++int
++isprint_l (int c, locale_t locobj)
++{
++ return ((&locobj->ctype[1])[c] &
++ (___ctype_upper | ___ctype_lower | ___ctype_digit | ___ctype_punc |
++ ___ctype_white)) && !((&locobj->ctype[1])[c] & ___ctype_ctrl);
++}
+Index: libunixlib/ctype/ispunct.c
+===================================================================
+--- libunixlib/ctype/ispunct.c (revision 7698)
++++ libunixlib/ctype/ispunct.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (ispunct) (int c)
+@@ -10,3 +11,8 @@
+ return ispunct (c);
+ }
+
++int
++ispunct_l (int c, locale_t locobj)
++{
++ return ((&locobj->ctype[1])[c] & ___ctype_punc);
++}
+Index: libunixlib/ctype/isspace.c
+===================================================================
+--- libunixlib/ctype/isspace.c (revision 7698)
++++ libunixlib/ctype/isspace.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (isspace) (int c)
+@@ -10,3 +11,8 @@
+ return isspace (c);
+ }
+
++int
++isspace_l (int c, locale_t locobj)
++{
++ return ((&locobj->ctype[1])[c] & ___ctype_white);
++}
+Index: libunixlib/ctype/isupper.c
+===================================================================
+--- libunixlib/ctype/isupper.c (revision 7698)
++++ libunixlib/ctype/isupper.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (isupper) (int c)
+@@ -10,3 +11,8 @@
+ return isupper (c);
+ }
+
++int
++isupper_l (int c, locale_t locobj)
++{
++ return ((&locobj->ctype[1])[c] & ___ctype_upper);
++}
+Index: libunixlib/ctype/isxdigit.c
+===================================================================
+--- libunixlib/ctype/isxdigit.c (revision 7698)
++++ libunixlib/ctype/isxdigit.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (isxdigit) (int c)
+@@ -10,3 +11,8 @@
+ return isxdigit (c);
+ }
+
++int
++isxdigit_l (int c, locale_t locobj)
++{
++ return ((&locobj->ctype[1])[c] & ___ctype_xdigit);
++}
+Index: libunixlib/ctype/toascii.c
+===================================================================
+--- libunixlib/ctype/toascii.c (revision 7698)
++++ libunixlib/ctype/toascii.c (working copy)
+@@ -10,3 +10,9 @@
+ return toascii (c);
+ }
+
++int
++toascii_l (int c, locale_t locobj)
++{
++ (void) locobj;
++ return toascii (c);
++}
+Index: libunixlib/ctype/tolower.c
+===================================================================
+--- libunixlib/ctype/tolower.c (revision 7698)
++++ libunixlib/ctype/tolower.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (tolower) (int c)
+@@ -10,3 +11,8 @@
+ return tolower (c);
+ }
+
++int
++tolower_l (int c, locale_t locobj)
++{
++ return (&locobj->ctype_lower[1])[c];
++}
+Index: libunixlib/ctype/toupper.c
+===================================================================
+--- libunixlib/ctype/toupper.c (revision 7698)
++++ libunixlib/ctype/toupper.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (toupper) (int c)
+@@ -10,3 +11,8 @@
+ return toupper (c);
+ }
+
++int
++toupper_l (int c, locale_t locobj)
++{
++ return (&locobj->ctype_upper[1])[c];
++}
+Index: libunixlib/incl-local/locale.h
+===================================================================
+--- libunixlib/incl-local/locale.h (revision 7698)
++++ libunixlib/incl-local/locale.h (working copy)
+@@ -13,15 +13,36 @@
+
+ #ifndef __TARGET_SCL__
+
+-/* Territory number for each locale. C locale is -1. */
+-extern int __locale_territory[LC_ALL + 1];
++struct _locale {
++ /* Map from locale category to territory number. C locale is -1. */
++ int locale_territory[LC_ALL];
+
+-/* Set to 1 is setlocale has been called since the last call to
+- localeconv. localeconv uses this flag to cache the lconv structure. */
+-extern int __setlocale_called;
++ /* Character type LUTs: EOF + one entry per character
++ *
++ * EOF is defined as -1, so character entries start at offset 1.
++ */
++ short ctype_upper[257];
++ short ctype_lower[257];
++ unsigned char ctype[257];
+
+-extern void __build_ctype_tables (int __territory) __THROW;
++ /* Set to 1 if the locale information has changed since the last time
++ * the lconv structure was updated. */
++ int lc_needs_refresh;
++ /* Numeric formatting information for locale */
++ struct lconv lc;
++};
+
++extern struct _locale __locale_global;
++
++extern void __build_ctype_tables (locale_t locobj, int __territory) __THROW;
++
++extern char *__setlocale_l (locale_t locobj, int __category,
++ const char *__locale) __THROW;
++
++void __localeconv_lconv_init (struct lconv *lc);
++void __localeconv_lconv_fini (struct lconv *lc);
++void __localeconv_l (locale_t locobj);
++
+ #endif
+
+ __END_DECLS
+Index: libunixlib/include/bits/locale_t.h
+===================================================================
+--- libunixlib/include/bits/locale_t.h (nonexistent)
++++ libunixlib/include/bits/locale_t.h (working copy)
+@@ -0,0 +1,10 @@
++/*
++ * Copyright (c) 2022 UnixLib Developers
++ */
++
++#ifndef _BITS_LOCALE_T_H_
++#define _BITS_LOCALE_T_H_
++
++typedef struct _locale *locale_t;
++
++#endif
+Index: libunixlib/include/ctype.h
+===================================================================
+--- libunixlib/include/ctype.h (revision 7698)
++++ libunixlib/include/ctype.h (working copy)
+@@ -51,6 +51,48 @@
+ extern int isblank (int __c) __THROW;
+
+ #ifndef __TARGET_SCL__
++# ifdef __USE_XOPEN2K8
++# include <bits/locale_t.h>
++
++/* c is alphabetic or numeric. */
++extern int isalnum_l (int __c, locale_t locobj) __THROW;
++
++/* c is alphabetic. */
++extern int isalpha_l (int __c, locale_t locobj) __THROW;
++
++/* c is a control character. */
++extern int iscntrl_l (int __c, locale_t locobj) __THROW;
++
++/* c is a decimal digit. */
++extern int isdigit_l (int __c, locale_t locobj) __THROW;
++
++/* c is any printable character other than a space. */
++extern int isgraph_l (int __c, locale_t locobj) __THROW;
++
++/* c is a lower-case letter. */
++extern int islower_l (int __c, locale_t locobj) __THROW;
++
++/* c is an upper-case letter. */
++extern int isupper_l (int __c, locale_t locobj) __THROW;
++
++/* c is a printable character. */
++extern int isprint_l (int __c, locale_t locobj) __THROW;
++
++/* c is a printable character other than a space or a
++ alphanumeric character. */
++extern int ispunct_l (int __c, locale_t locobj) __THROW;
++
++/* c is a white space character e.g. space, newline, tab, linefeed,
++ return, vertical tab. */
++extern int isspace_l (int __c, locale_t locobj) __THROW;
++
++/* c is a hex digit. */
++extern int isxdigit_l (int __c, locale_t locobj) __THROW;
++
++/* c is tab or space. */
++extern int isblank_l (int __c, locale_t locobj) __THROW;
++# endif
++
+ /* Characteristics. */
+ extern const unsigned char * const __ctype;
+ /* Lower case table. */
+@@ -108,6 +150,10 @@
+ extern int toupper (int __c) __THROW;
+ #ifndef __TARGET_SCL__
+ # define toupper(c) ((int) __ctype_upper[(int) (c)])
++
++# ifdef __USE_XOPEN2K8
++extern int toupper_l (int __c, locale_t locobj) __THROW;
++# endif
+ #endif
+
+ /* Convert c to lower case. */
+@@ -114,6 +160,10 @@
+ extern int tolower (int __c) __THROW;
+ #ifndef __TARGET_SCL__
+ # define tolower(c) ((int) __ctype_lower[(int) (c)])
++
++# ifdef __USE_XOPEN2K8
++extern int tolower_l (int __c, locale_t locobj) __THROW;
++# endif
+ #endif
+
+ #ifndef __TARGET_SCL__
+@@ -135,6 +185,11 @@
+ /* Is c an ASCII character. */
+ extern int isascii (int __c) __THROW;
+ # define isascii(c) ((unsigned)(c) <= 0x7f)
++
++# ifdef __USE_XOPEN2K8
++extern int toascii_l (int __c, locale_t locobj) __THROW;
++extern int isascii_l (int __c, locale_t locobj) __THROW;
++# endif
+ # endif
+ #endif
+
+Index: libunixlib/include/langinfo.h
+===================================================================
+--- libunixlib/include/langinfo.h (revision 7698)
++++ libunixlib/include/langinfo.h (working copy)
+@@ -580,18 +580,12 @@
+ extern char *nl_langinfo (nl_item __item) __THROW;
+
+
+-#if 0
+-#ifdef __USE_GNU
+-/* This interface is for the extended locale model. See <locale.h> for
+- more information. */
++#ifdef __USE_XOPEN2K8
++# include <bits/locale_t.h>
+
+-/* Get locale datatype definition. */
+-# include <xlocale.h>
+-
+ /* Just like nl_langinfo but get the information from the locale object L. */
+-extern char *nl_langinfo_l (nl_item __item, __locale_t l);
++extern char *nl_langinfo_l (nl_item __item, locale_t __l);
+ #endif
+-#endif
+
+ __END_DECLS
+
+Index: libunixlib/include/locale.h
+===================================================================
+--- libunixlib/include/locale.h (revision 7698)
++++ libunixlib/include/locale.h (working copy)
+@@ -33,16 +33,16 @@
+ /* Entire locale. */
+ # define LC_ALL 6
+
+-#define LC_COLLATE_MASK (1L << 1)
+-#define LC_CTYPE_MASK (1L << 2)
+-#define LC_MESSAGES_MASK (1L << 3)
+-#define LC_MONETARY_MASK (1L << 4)
+-#define LC_NUMERIC_MASK (1L << 5)
+-#define LC_TIME_MASK (1L << 6)
+-#define LC_ALL_MASK (LC_COLLATE_MASK | LC_CTYPE_MASK | LC_MESSAGES_MASK | LC_MONETARY_MASK | LC_NUMERIC_MASK | LC_TIME_MASK)
++# ifdef __USE_XOPEN2K8
++# define LC_COLLATE_MASK (1L << 0)
++# define LC_CTYPE_MASK (1L << 1)
++# define LC_MESSAGES_MASK (1L << 2)
++# define LC_MONETARY_MASK (1L << 3)
++# define LC_NUMERIC_MASK (1L << 4)
++# define LC_TIME_MASK (1L << 5)
++# define LC_ALL_MASK (LC_COLLATE_MASK | LC_CTYPE_MASK | LC_MESSAGES_MASK | LC_MONETARY_MASK | LC_NUMERIC_MASK | LC_TIME_MASK)
++# endif
+
+-typedef struct _locale *locale_t;
+-
+ #else
+ /* String collation (functions 'strcoll' and 'strxfrm'). */
+ # define LC_COLLATE 1
+@@ -121,6 +121,9 @@
+ extern struct lconv *localeconv (void) __THROW;
+
+ #ifndef __TARGET_SCL__
++# ifdef __USE_XOPEN2K8
++# include <bits/locale_t.h>
++
+ extern locale_t uselocale(locale_t newloc);
+
+ extern void freelocale(locale_t locobj);
+@@ -127,7 +130,11 @@
+
+ extern locale_t newlocale(int category_mask, const char *locale,
+ locale_t base);
+-# define LC_GLOBAL_LOCALE ((locale_t) -1L)
++
++extern locale_t duplocale(locale_t locobj);
++
++# define LC_GLOBAL_LOCALE ((locale_t) -1L)
++# endif
+ #endif
+
+ __END_NAMESPACE_STD
+Index: libunixlib/include/string.h
+===================================================================
+--- libunixlib/include/string.h (revision 7698)
++++ libunixlib/include/string.h (working copy)
+@@ -93,6 +93,16 @@
+ const char *__restrict __src, size_t __n)
+ __THROW __nonnull ((2));
+
++#ifdef __USE_XOPEN2K8
++#include <bits/locale_t.h>
++
++extern int strcoll_l (const char *__s1, const char *__s2, locale_t __l)
++ __THROW __attribute_pure__ __nonnull ((1, 2, 3));
++
++extern size_t strxfrm_l (char *__dest, const char *__src, size_t __n,
++ locale_t __l) __THROW __nonnull ((2, 4));
++#endif
++
+ /* Find the first occurrence of c in s. */
+ extern char *strchr (const char *__s, int __c)
+ __THROW __attribute_pure__ __nonnull ((1)) __wur;
+@@ -281,6 +291,17 @@
+ /* Compare no more than N chars of S1 and S2, ignoring case. */
+ extern int strncasecmp (const char *__s1, const char *__s2, size_t __n)
+ __THROW __attribute_pure__ __nonnull ((1, 2)) __wur;
++
++# ifdef __USE_XOPEN2K8
++# include <bits/locale_t.h>
++
++extern int strcasecmp_l (const char *__s1, const char *__s2, locale_t __loc)
++ __THROW __attribute_pure__ __nonnull ((1, 2, 3));
++
++extern int strncasecmp_l (const char *__s1, const char *__s2,
++ size_t __n, locale_t __loc)
++ __THROW __attribute_pure__ __nonnull ((1, 2, 4));
++# endif
+ #endif /* Use BSD. */
+
+ #if defined __USE_XOPEN2K || defined __USE_MISC
+@@ -289,6 +310,11 @@
+ __THROW __nonnull ((2));
+ #endif
+
++#ifdef __USE_XOPEN2K8
++/* Translate error number to string according to the locale L. */
++extern char *strerror_l (int __errnum, locale_t __l) __THROW;
++#endif
++
+ #ifndef __TARGET_SCL__
+ # ifndef basename
+ /* Return the file name within directory of FILENAME. We don't
+Index: libunixlib/include/strings.h
+===================================================================
+--- libunixlib/include/strings.h (revision 7698)
++++ libunixlib/include/strings.h (working copy)
+@@ -37,7 +37,17 @@
+ /* Compare n chars of S1 and S2, ignoring case. */
+ extern int strncasecmp (const char *__s1, const char *__s2, size_t __n);
+
++# ifdef __USE_XOPEN2K8
++# include <bits/locale_t.h>
+
++extern int strcasecmp_l (const char *__s1, const char *__s2, locale_t __loc)
++ __THROW __attribute_pure__ __nonnull ((1, 2, 3));
++
++extern int strncasecmp_l (const char *__s1, const char *__s2,
++ size_t __n, locale_t __loc)
++ __THROW __attribute_pure__ __nonnull ((1, 2, 4));
++# endif
++
+ /* Return the position of the first bit set in I, or 0 if none are set.
+ The least-significant bit is position 1, the most-significant 32. */
+ extern int ffs (int __i);
+Index: libunixlib/include/wchar.h
+===================================================================
+--- libunixlib/include/wchar.h (revision 7698)
++++ libunixlib/include/wchar.h (working copy)
+@@ -1,7 +1,7 @@
+ /*
+ * File taken from glibc 2.11.
+ * Following changes were made:
+- * - Disabled non-standard reentrant locale prototypes.
++ * - None
+ */
+
+ /* Copyright (C) 1995-2008, 2009 Free Software Foundation, Inc.
+@@ -172,7 +172,6 @@
+ __END_NAMESPACE_STD
+ #endif
+
+-#if 0
+ #ifdef __USE_XOPEN2K8
+ /* Compare S1 and S2, ignoring case. */
+ extern int wcscasecmp (__const wchar_t *__s1, __const wchar_t *__s2) __THROW;
+@@ -183,15 +182,14 @@
+
+ /* Similar to the two functions above but take the information from
+ the provided locale and not the global locale. */
+-# include <xlocale.h>
++# include <bits/locale_t.h>
+
+ extern int wcscasecmp_l (__const wchar_t *__s1, __const wchar_t *__s2,
+- __locale_t __loc) __THROW;
++ locale_t __loc) __THROW;
+
+ extern int wcsncasecmp_l (__const wchar_t *__s1, __const wchar_t *__s2,
+- size_t __n, __locale_t __loc) __THROW;
++ size_t __n, locale_t __loc) __THROW;
+ #endif
+-#endif
+
+ __BEGIN_NAMESPACE_STD
+ /* Compare S1 and S2, both interpreted as appropriate to the
+@@ -205,7 +203,6 @@
+ __END_NAMESPACE_STD
+
+ #ifdef __USE_XOPEN2K8
+-#if 0
+ /* Similar to the two functions above but take the information from
+ the provided locale and not the global locale. */
+
+@@ -212,14 +209,13 @@
+ /* Compare S1 and S2, both interpreted as appropriate to the
+ LC_COLLATE category of the given locale. */
+ extern int wcscoll_l (__const wchar_t *__s1, __const wchar_t *__s2,
+- __locale_t __loc) __THROW;
++ locale_t __loc) __THROW;
+
+ /* Transform S2 into array pointed to by S1 such that if wcscmp is
+ applied to two transformed strings the result is the as applying
+ `wcscoll' to the original strings. */
+ extern size_t wcsxfrm_l (wchar_t *__s1, __const wchar_t *__s2,
+- size_t __n, __locale_t __loc) __THROW;
+-#endif
++ size_t __n, locale_t __loc) __THROW;
+
+ #ifndef __TARGET_SCL__
+ /* Duplicate S, returning an identical malloc'd string. */
+Index: libunixlib/include/wctype.h
+===================================================================
+--- libunixlib/include/wctype.h (revision 7698)
++++ libunixlib/include/wctype.h (working copy)
+@@ -3,7 +3,6 @@
+ * Following changes were made:
+ * - Replaced "#include <bits/types.h>" into "#include <unixlib/types.h>"
+ * - Add wint_t typedef when it hasn't been defined in stddef.h.
+- * - Disabled non-standard reentrant locale prototypes.
+ */
+
+ /* Copyright (C) 1996-2002,2005,2007,2008,2009 Free Software Foundation, Inc.
+@@ -191,7 +190,6 @@
+ /* Determine whether the wide-character WC has the property described by
+ DESC. */
+ extern int iswctype (wint_t __wc, wctype_t __desc) __THROW;
+-#define iswctype_l(c, d, l) iswctype(c, d)
+
+ __END_NAMESPACE_C99
+
+@@ -241,73 +239,71 @@
+ extern wint_t towctrans (wint_t __wc, wctrans_t __desc) __THROW;
+ __END_NAMESPACE_C99
+
+-#if 0
+ # ifdef __USE_XOPEN2K8
+-/* Declare the interface to extended locale model. */
+-# include <xlocale.h>
++# include <bits/locale_t.h>
+
+ /* Test for any wide character for which `iswalpha' or `iswdigit' is
+ true. */
+-extern int iswalnum_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswalnum_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Test for any wide character for which `iswupper' or 'iswlower' is
+ true, or any wide character that is one of a locale-specific set of
+ wide-characters for which none of `iswcntrl', `iswdigit',
+ `iswpunct', or `iswspace' is true. */
+-extern int iswalpha_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswalpha_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Test for any control wide character. */
+-extern int iswcntrl_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswcntrl_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Test for any wide character that corresponds to a decimal-digit
+ character. */
+-extern int iswdigit_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswdigit_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Test for any wide character for which `iswprint' is true and
+ `iswspace' is false. */
+-extern int iswgraph_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswgraph_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Test for any wide character that corresponds to a lowercase letter
+ or is one of a locale-specific set of wide characters for which
+ none of `iswcntrl', `iswdigit', `iswpunct', or `iswspace' is true. */
+-extern int iswlower_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswlower_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Test for any printing wide character. */
+-extern int iswprint_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswprint_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Test for any printing wide character that is one of a
+ locale-specific et of wide characters for which neither `iswspace'
+ nor `iswalnum' is true. */
+-extern int iswpunct_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswpunct_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Test for any wide character that corresponds to a locale-specific
+ set of wide characters for which none of `iswalnum', `iswgraph', or
+ `iswpunct' is true. */
+-extern int iswspace_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswspace_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Test for any wide character that corresponds to an uppercase letter
+ or is one of a locale-specific set of wide character for which none
+ of `iswcntrl', `iswdigit', `iswpunct', or `iswspace' is true. */
+-extern int iswupper_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswupper_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Test for any wide character that corresponds to a hexadecimal-digit
+ character equivalent to that performed be the functions described
+ in the previous subclause. */
+-extern int iswxdigit_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswxdigit_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Test for any wide character that corresponds to a standard blank
+ wide character or a locale-specific set of wide characters for
+ which `iswalnum' is false. */
+-extern int iswblank_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswblank_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Construct value that describes a class of wide characters identified
+ by the string argument PROPERTY. */
+-extern wctype_t wctype_l (__const char *__property, __locale_t __locale)
++extern wctype_t wctype_l (__const char *__property, locale_t __locale)
+ __THROW;
+
+ /* Determine whether the wide-character WC has the property described by
+ DESC. */
+-extern int iswctype_l (wint_t __wc, wctype_t __desc, __locale_t __locale)
++extern int iswctype_l (wint_t __wc, wctype_t __desc, locale_t __locale)
+ __THROW;
+
+
+@@ -316,22 +312,21 @@
+ */
+
+ /* Converts an uppercase letter to the corresponding lowercase letter. */
+-extern wint_t towlower_l (wint_t __wc, __locale_t __locale) __THROW;
++extern wint_t towlower_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Converts an lowercase letter to the corresponding uppercase letter. */
+-extern wint_t towupper_l (wint_t __wc, __locale_t __locale) __THROW;
++extern wint_t towupper_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Construct value that describes a mapping between wide characters
+ identified by the string argument PROPERTY. */
+-extern wctrans_t wctrans_l (__const char *__property, __locale_t __locale)
++extern wctrans_t wctrans_l (__const char *__property, locale_t __locale)
+ __THROW;
+
+ /* Map the wide character WC using the mapping described by DESC. */
+ extern wint_t towctrans_l (wint_t __wc, wctrans_t __desc,
+- __locale_t __locale) __THROW;
++ locale_t __locale) __THROW;
+
+ # endif /* Use POSIX 2008. */
+-#endif
+
+ __END_DECLS
+
+Index: libunixlib/locale/localeconv.c
+===================================================================
+--- libunixlib/locale/localeconv.c (revision 7698)
++++ libunixlib/locale/localeconv.c (working copy)
+@@ -14,8 +14,6 @@
+
+ /* #define DEBUG */
+
+-int __setlocale_called = 1;
+-
+ static int
+ read_symbol (int reason_code, int territory)
+ {
+@@ -71,26 +69,44 @@
+ *grouping = new_grouping;
+ }
+
+-static struct lconv lc = { NULL, NULL, NULL, NULL, NULL,
+- NULL, NULL, NULL, NULL, NULL,
+- CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX,
+- CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX };
++void
++__localeconv_lconv_init (struct lconv *lc)
++{
++ memset(lc, 0, sizeof(*lc));
++ lc->int_frac_digits = lc->frac_digits = lc->p_cs_precedes =
++ lc->p_sep_by_space = lc->n_cs_precedes = lc->n_sep_by_space =
++ lc->p_sign_posn = lc->n_sign_posn = CHAR_MAX;
++}
+
+-/* Defined by POSIX as not threadsafe */
+-struct lconv *
+-localeconv (void)
++void
++__localeconv_lconv_fini (struct lconv *lc)
+ {
++ free(lc->decimal_point);
++ free(lc->thousands_sep);
++ free(lc->grouping);
++ free(lc->int_curr_symbol);
++ free(lc->currency_symbol);
++ free(lc->mon_decimal_point);
++ free(lc->mon_thousands_sep);
++ free(lc->mon_grouping);
++ free(lc->positive_sign);
++ free(lc->negative_sign);
++}
++
++void
++__localeconv_l (locale_t locobj)
++{
+ int numeric, monetary;
+
+ /* If setlocale has not been called since the last call to
+ localeconv, then the lconv structure will be the same. */
+- if (!__setlocale_called)
+- return &lc;
++ if (!locobj->lc_needs_refresh)
++ return;
+
+- __setlocale_called = 0;
++ locobj->lc_needs_refresh = 0;
+
+- numeric = __locale_territory[LC_NUMERIC];
+- monetary = __locale_territory[LC_MONETARY];
++ numeric = locobj->locale_territory[LC_NUMERIC];
++ monetary = locobj->locale_territory[LC_MONETARY];
+
+ /* See the PRMs regarding SWI Territory_ReadSymbols for the
+ meanings of the following numbers. */
+@@ -97,71 +113,80 @@
+ if (numeric == -1)
+ {
+ /* We're using the 'C' locale. */
+- free (lc.decimal_point);
+- lc.decimal_point = strdup (".");
+- free (lc.thousands_sep);
+- lc.thousands_sep = strdup ("");
+- free (lc.grouping);
+- lc.grouping = strdup ("");
++ free (locobj->lc.decimal_point);
++ locobj->lc.decimal_point = strdup (".");
++ free (locobj->lc.thousands_sep);
++ locobj->lc.thousands_sep = strdup ("");
++ free (locobj->lc.grouping);
++ locobj->lc.grouping = strdup ("");
+ }
+ else
+ {
+- free (lc.decimal_point);
+- lc.decimal_point = strdup ((char *) read_symbol (0, numeric));
+- free (lc.thousands_sep);
+- lc.thousands_sep = strdup ((char *) read_symbol (1, numeric));
+- read_byte_list (2, &lc.grouping, numeric);
++ free (locobj->lc.decimal_point);
++ locobj->lc.decimal_point = strdup ((char *) read_symbol (0, numeric));
++ free (locobj->lc.thousands_sep);
++ locobj->lc.thousands_sep = strdup ((char *) read_symbol (1, numeric));
++ read_byte_list (2, &locobj->lc.grouping, numeric);
+ }
+ if (monetary == -1)
+ {
+ /* We using the 'C' locale. Empty strings and CHAR_MAX means
+ that these fields are unspecified. */
+- free (lc.mon_decimal_point);
+- lc.mon_decimal_point = strdup ("");
+- free (lc.mon_thousands_sep);
+- lc.mon_thousands_sep = strdup ("");
+- free (lc.mon_grouping);
+- lc.mon_grouping = strdup ("");
+- lc.int_frac_digits = CHAR_MAX;
+- lc.frac_digits = CHAR_MAX;
+- free (lc.currency_symbol);
+- lc.currency_symbol = strdup ("");
+- free (lc.int_curr_symbol);
+- lc.int_curr_symbol = strdup ("");
+- lc.p_cs_precedes = CHAR_MAX;
+- lc.n_cs_precedes = CHAR_MAX;
+- lc.p_sep_by_space = CHAR_MAX;
+- lc.n_sep_by_space = CHAR_MAX;
+- free (lc.positive_sign);
+- lc.positive_sign = strdup ("");
+- free (lc.negative_sign);
+- lc.negative_sign = strdup ("");
+- lc.p_sign_posn = CHAR_MAX;
+- lc.n_sign_posn = CHAR_MAX;
++ free (locobj->lc.mon_decimal_point);
++ locobj->lc.mon_decimal_point = strdup ("");
++ free (locobj->lc.mon_thousands_sep);
++ locobj->lc.mon_thousands_sep = strdup ("");
++ free (locobj->lc.mon_grouping);
++ locobj->lc.mon_grouping = strdup ("");
++ locobj->lc.int_frac_digits = CHAR_MAX;
++ locobj->lc.frac_digits = CHAR_MAX;
++ free (locobj->lc.currency_symbol);
++ locobj->lc.currency_symbol = strdup ("");
++ free (locobj->lc.int_curr_symbol);
++ locobj->lc.int_curr_symbol = strdup ("");
++ locobj->lc.p_cs_precedes = CHAR_MAX;
++ locobj->lc.n_cs_precedes = CHAR_MAX;
++ locobj->lc.p_sep_by_space = CHAR_MAX;
++ locobj->lc.n_sep_by_space = CHAR_MAX;
++ free (locobj->lc.positive_sign);
++ locobj->lc.positive_sign = strdup ("");
++ free (locobj->lc.negative_sign);
++ locobj->lc.negative_sign = strdup ("");
++ locobj->lc.p_sign_posn = CHAR_MAX;
++ locobj->lc.n_sign_posn = CHAR_MAX;
+ }
+ else
+ {
+- free (lc.int_curr_symbol);
+- lc.int_curr_symbol = strdup ((char *)read_symbol (3, monetary));
+- free (lc.currency_symbol);
+- lc.currency_symbol = strdup ((char *)read_symbol (4, monetary));
+- free (lc.mon_decimal_point);
+- lc.mon_decimal_point = strdup ((char *)read_symbol (5, monetary));
+- free (lc.mon_thousands_sep);
+- lc.mon_thousands_sep = strdup ((char *)read_symbol (6, monetary));
+- read_byte_list (7, &lc.mon_grouping, monetary);
+- free (lc.positive_sign);
+- lc.positive_sign = strdup ((char *)read_symbol (8, monetary));
+- free (lc.negative_sign);
+- lc.negative_sign = strdup ((char *)read_symbol (9, monetary));
+- lc.int_frac_digits = (char)read_symbol (10, monetary);
+- lc.frac_digits = (char)read_symbol (11, monetary);
+- lc.p_cs_precedes = (char)read_symbol (12, monetary);
+- lc.p_sep_by_space = (char)read_symbol (13, monetary);
+- lc.n_cs_precedes = (char)read_symbol (14, monetary);
+- lc.n_sep_by_space = (char)read_symbol (15, monetary);
+- lc.p_sign_posn = (char)read_symbol (16, monetary);
+- lc.n_sign_posn = (char)read_symbol (17, monetary);
++ free (locobj->lc.int_curr_symbol);
++ locobj->lc.int_curr_symbol = strdup ((char *)read_symbol (3, monetary));
++ free (locobj->lc.currency_symbol);
++ locobj->lc.currency_symbol = strdup ((char *)read_symbol (4, monetary));
++ free (locobj->lc.mon_decimal_point);
++ locobj->lc.mon_decimal_point = strdup ((char *)read_symbol (5, monetary));
++ free (locobj->lc.mon_thousands_sep);
++ locobj->lc.mon_thousands_sep = strdup ((char *)read_symbol (6, monetary));
++ read_byte_list (7, &locobj->lc.mon_grouping, monetary);
++ free (locobj->lc.positive_sign);
++ locobj->lc.positive_sign = strdup ((char *)read_symbol (8, monetary));
++ free (locobj->lc.negative_sign);
++ locobj->lc.negative_sign = strdup ((char *)read_symbol (9, monetary));
++ locobj->lc.int_frac_digits = (char)read_symbol (10, monetary);
++ locobj->lc.frac_digits = (char)read_symbol (11, monetary);
++ locobj->lc.p_cs_precedes = (char)read_symbol (12, monetary);
++ locobj->lc.p_sep_by_space = (char)read_symbol (13, monetary);
++ locobj->lc.n_cs_precedes = (char)read_symbol (14, monetary);
++ locobj->lc.n_sep_by_space = (char)read_symbol (15, monetary);
++ locobj->lc.p_sign_posn = (char)read_symbol (16, monetary);
++ locobj->lc.n_sign_posn = (char)read_symbol (17, monetary);
+ }
+- return &lc;
++ return;
+ }
++
++/* Defined by POSIX as not threadsafe */
++struct lconv *
++localeconv (void)
++{
++ __localeconv_l (&__locale_global);
++
++ return &__locale_global.lc;
++}
+Index: libunixlib/locale/newlocale.c
+===================================================================
+--- libunixlib/locale/newlocale.c (revision 7698)
++++ libunixlib/locale/newlocale.c (working copy)
+@@ -1,17 +1,17 @@
+ /* Copyright (c) 2019 UnixLib Developers
+ */
+
++#include <ctype.h>
++#include <errno.h>
++#include <locale.h>
+ #include <stdlib.h>
+-#include <locale.h>
+ #include <stdio.h>
+-#include <errno.h>
++#include <string.h>
+
+-struct _locale {
+- struct lconv lc;
+-};
++#include <internal/unix.h>
+
+ /* This is supposed to be per-thread. */
+-static locale_t current_locale;
++static locale_t current_locale = LC_GLOBAL_LOCALE;
+
+ locale_t uselocale(locale_t newloc)
+ {
+@@ -27,20 +27,94 @@
+
+ void freelocale(locale_t locobj)
+ {
+- if (locobj)
++ if (locobj) {
++ __localeconv_lconv_fini(&locobj->lc);
+ free(locobj);
++ }
+ }
+
+ locale_t newlocale(int category_mask, const char *locale,
+ locale_t base)
+ {
+- locale_t loc = (locale_t)malloc(sizeof(*loc));
+- if (!loc) {
++ struct _locale tmp;
++
++ PTHREAD_UNSAFE
++
++ if ((category_mask & ~LC_ALL_MASK) || locale == NULL) {
++ __set_errno (EINVAL);
++ return 0;
++ }
++
++ /* The locale provided will be verified by __setlocale_l() */
++
++ /* Prepare the temporary locale we will modify */
++ if (base != 0 && base != LC_GLOBAL_LOCALE) {
++ memcpy(&tmp, base, sizeof(tmp));
++ } else {
++ if (base == LC_GLOBAL_LOCALE) {
++ /* Undefined: be helpful to client */
++ memcpy(&tmp, &__locale_global, sizeof(tmp));
++ } else {
++ /* Initialise to C locale */
++ __build_ctype_tables(&tmp, -2);
++ }
++ }
++
++ /* Now, apply the requested locale to each of the categories in the mask */
++ if (category_mask == LC_ALL_MASK) {
++ /* Special-case LC_ALL to handle the encoded locale string */
++ if (__setlocale_l(&tmp, LC_ALL, locale) == NULL) {
++ return 0;
++ }
++ } else {
++ int category = 0, mask = category_mask;
++ while (mask != 0) {
++ if (mask & 1) {
++ if (__setlocale_l(&tmp, category, locale) == NULL) {
++ return 0;
++ }
++ }
++ category++;
++ mask >>= 1;
++ }
++ }
++
++ /* Allocate the result, if necessary */
++ if (base == 0 || base == LC_GLOBAL_LOCALE) {
++ base = (locale_t)malloc(sizeof(*base));
++ if (!base) {
++ __set_errno (ENOMEM);
++ return 0;
++ }
++ }
++ /* Fill it in */
++ memcpy(base, &tmp, sizeof(tmp));
++
++ /* Mark the lconv data stale */
++ base->lc_needs_refresh = 1;
++
++ return base;
++}
++
++locale_t duplocale(locale_t locobj)
++{
++ locale_t loc;
++
++ loc = (locale_t) malloc(sizeof(*loc));
++ if (loc == NULL) {
+ __set_errno (ENOMEM);
+ return 0;
+ }
+
+- loc->lc = *localeconv();
++ if (locobj == LC_GLOBAL_LOCALE) {
++ memcpy(loc, &__locale_global, sizeof(*loc));
++ } else {
++ memcpy(loc, locobj, sizeof(*loc));
++ }
+
++ /* Invalidate lconv in the copy */
++ __localeconv_lconv_init(&loc->lc);
++ loc->lc_needs_refresh = 1;
++
+ return loc;
+ }
+Index: libunixlib/locale/nl_langinfo.c
+===================================================================
+--- libunixlib/locale/nl_langinfo.c (revision 7698)
++++ libunixlib/locale/nl_langinfo.c (working copy)
+@@ -24,3 +24,10 @@
+
+ return (char *)value;
+ }
++
++char *
++nl_langinfo_l (nl_item item, locale_t l)
++{
++ (void) l;
++ return nl_langinfo(item);
++}
+Index: libunixlib/locale/setlocale.c
+===================================================================
+--- libunixlib/locale/setlocale.c (revision 7698)
++++ libunixlib/locale/setlocale.c (working copy)
+@@ -195,7 +195,7 @@
+ }
+
+ static void
+-do_lc_all (char *buffer, int size)
++do_lc_all (locale_t locobj, char *buffer, int size)
+ {
+ char temp[64];
+ int category, same = 1;
+@@ -204,13 +204,13 @@
+ setlocale to set all locales. If all locales are
+ the same, then we can produce a very short string. */
+ for (category = 1; category < LC_ALL; ++category)
+- if (__locale_territory[0] != __locale_territory[category])
++ if (locobj->locale_territory[0] != locobj->locale_territory[category])
+ same = 0;
+
+ if (same)
+ {
+ /* All locales are set to the same territory. */
+- territory_name (__locale_territory[0], buffer, size);
++ territory_name (locobj->locale_territory[0], buffer, size);
+ }
+ else
+ {
+@@ -218,7 +218,7 @@
+ LC_CATEGORY=country;LC_CATEGORY=country; ... */
+ for (category = 0; category < LC_ALL; ++category)
+ {
+- territory_name (__locale_territory[category], temp, sizeof (temp));
++ territory_name (locobj->locale_territory[category], temp, sizeof (temp));
+ buffer = stpcpy (buffer, locale_names[category]);
+ *buffer++ = '=';
+ buffer = stpcpy (buffer, temp);
+@@ -230,15 +230,13 @@
+ }
+
+ char *
+-setlocale (int category, const char *locale)
++__setlocale_l (locale_t locobj, int category, const char *locale)
+ {
+ int new_territory, changed;
+ static char old_locale[256];
+
+- PTHREAD_UNSAFE
+-
+ /* This tells localeconv to re-read data for the lconv structure. */
+- __setlocale_called = 1;
++ locobj->lc_needs_refresh = 1;
+
+ if (locale == NULL)
+ {
+@@ -247,11 +245,11 @@
+ {
+ /* The locale string is specially encoded for LC_ALL so we
+ could restore all locales at any time. */
+- do_lc_all (old_locale, sizeof (old_locale));
++ do_lc_all (locobj, old_locale, sizeof (old_locale));
+ return old_locale;
+ }
+
+- territory_name (__locale_territory[category], old_locale, sizeof (old_locale));
++ territory_name (locobj->locale_territory[category], old_locale, sizeof (old_locale));
+ return old_locale;
+ }
+
+@@ -270,7 +268,7 @@
+ /* Encode the locale string, as we will be returning this
+ later. Remember, setlocale returns the locale settings
+ that are about to be changed. */
+- do_lc_all (old_locale, sizeof (old_locale));
++ do_lc_all (locobj, old_locale, sizeof (old_locale));
+
+ /* Check for an encoded (composite) name. Simply looking for
+ a semi-colon will verify this. */
+@@ -332,11 +330,11 @@
+
+ /* We now know all locales exist, so set them. */
+ for (category = 0; category < LC_ALL; ++category)
+- __locale_territory[category] = territory_number (newnames[category]);
++ locobj->locale_territory[category] = territory_number (newnames[category]);
+
+ /* Re-build the character type tables according to the new
+ locale settings. */
+- __build_ctype_tables (__locale_territory[LC_CTYPE]);
++ __build_ctype_tables (locobj, locobj->locale_territory[LC_CTYPE]);
+ return old_locale;
+ }
+ }
+@@ -359,9 +357,9 @@
+ /* Change the locale for all categories. old_locale was created
+ when we previously checked for a composite string. */
+ for (category = 0; category < LC_ALL; ++category)
+- if (__locale_territory[category] != new_territory)
++ if (locobj->locale_territory[category] != new_territory)
+ {
+- __locale_territory[category] = new_territory;
++ locobj->locale_territory[category] = new_territory;
+ changed = 1;
+ }
+ }
+@@ -368,12 +366,12 @@
+ else
+ {
+ /* Change the locale for just one category. */
+- territory_name (__locale_territory[category],
++ territory_name (locobj->locale_territory[category],
+ old_locale, sizeof (old_locale));
+
+- if (__locale_territory[category] != new_territory)
++ if (locobj->locale_territory[category] != new_territory)
+ {
+- __locale_territory[category] = new_territory;
++ locobj->locale_territory[category] = new_territory;
+ changed = 1;
+ }
+ }
+@@ -384,7 +382,16 @@
+ is changing. The GNU Java compiler is known to repeatedly call
+ setlocale. */
+ if (changed && (category == LC_ALL || category == LC_CTYPE))
+- __build_ctype_tables (new_territory);
++ __build_ctype_tables (locobj, new_territory);
+
+ return old_locale;
+ }
++
++char *
++setlocale (int category, const char *locale)
++{
++
++ PTHREAD_UNSAFE
++
++ return __setlocale_l(&__locale_global, category, locale);
++}
+Index: libunixlib/locale/strcoll.c
+===================================================================
+--- libunixlib/locale/strcoll.c (revision 7698)
++++ libunixlib/locale/strcoll.c (working copy)
+@@ -11,9 +11,15 @@
+ int
+ strcoll (const char *s1, const char *s2)
+ {
++ return strcoll_l (s1, s2, &__locale_global);
++}
++
++int
++strcoll_l (const char *s1, const char *s2, locale_t l)
++{
+ int regs[10];
+
+- regs[0] = __locale_territory[LC_COLLATE];
++ regs[0] = l->locale_territory[LC_COLLATE];
+ regs[1] = (int)s1;
+ regs[2] = (int)s2;
+ regs[3] = 0;
+@@ -21,3 +27,4 @@
+ __os_swi (Territory_Collate, regs);
+ return regs[0];
+ }
++
+Index: libunixlib/locale/strxfrm.c
+===================================================================
+--- libunixlib/locale/strxfrm.c (revision 7698)
++++ libunixlib/locale/strxfrm.c (working copy)
+@@ -11,9 +11,15 @@
+ size_t
+ strxfrm (char *to, const char *from, size_t size)
+ {
++ return strxfrm_l (to, from, size, &__locale_global);
++}
++
++size_t
++strxfrm_l (char *to, const char *from, size_t size, locale_t l)
++{
+ int regs[10];
+
+- regs[0] = __locale_territory[LC_COLLATE];
++ regs[0] = l->locale_territory[LC_COLLATE];
+ regs[1] = (int)to;
+ regs[2] = (int)from;
+ regs[3] = size;
+Index: libunixlib/locale/territory.c
+===================================================================
+--- libunixlib/locale/territory.c (revision 7698)
++++ libunixlib/locale/territory.c (nonexistent)
+@@ -1,10 +0,0 @@
+-/* __locale_territory
+- * Copyright (c) 2000-2006 UnixLib Developers
+- */
+-
+-#include <locale.h>
+-
+-/* Global used for all calls to the Territory module. These variable
+- contain the territory number as set by setlocale. A value of
+- -1 means use the C locale. */
+-int __locale_territory[LC_ALL + 1];
+Index: libunixlib/string/stricmp.c
+===================================================================
+--- libunixlib/string/stricmp.c (revision 7698)
++++ libunixlib/string/stricmp.c (working copy)
+@@ -4,6 +4,7 @@
+ #include <string.h>
+ #include <strings.h>
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ stricmp (const char *s1, const char *s2)
+@@ -26,3 +27,24 @@
+ return result;
+ }
+ strong_alias (stricmp, strcasecmp)
++
++int
++strcasecmp_l (const char *s1, const char *s2, locale_t locobj)
++{
++ const unsigned char *p1 = (const unsigned char *) s1;
++ const unsigned char *p2 = (const unsigned char *) s2;
++ int result = 0;
++
++ if (p1 == p2)
++ return result;
++
++ while (! result)
++ {
++ result = tolower_l (*p1, locobj) - tolower_l (*p2, locobj);
++ if (*p1++ == '\0')
++ break;
++ p2 ++;
++ }
++
++ return result;
++}
+Index: libunixlib/string/strnicmp.c
+===================================================================
+--- libunixlib/string/strnicmp.c (revision 7698)
++++ libunixlib/string/strnicmp.c (working copy)
+@@ -5,6 +5,7 @@
+ #include <string.h>
+ #include <strings.h>
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ strnicmp (const char *s1, const char *s2, size_t n)
+@@ -26,3 +27,22 @@
+ }
+ strong_alias (strnicmp, strncasecmp)
+
++int
++strncasecmp_l (const char *s1, const char *s2, size_t n, locale_t locobj)
++{
++ int i, j;
++
++ if (!n)
++ return 0;
++
++ do
++ {
++ i = *s1++, j = *s2++;
++ i = tolower_l (i, locobj);
++ j = tolower_l (j, locobj);
++ }
++ while (i && i == j && --n);
++
++ return i - j;
++}
++
+Index: libunixlib/sys/errlist.c
+===================================================================
+--- libunixlib/sys/errlist.c (revision 7698)
++++ libunixlib/sys/errlist.c (working copy)
+@@ -211,3 +211,10 @@
+
+ return 0;
+ }
++
++char *
++strerror_l (int errnum, locale_t l)
++{
++ (void) l;
++ return strerror (errnum);
++}
+Index: libunixlib/time/broken.c
+===================================================================
+--- libunixlib/time/broken.c (revision 7698)
++++ libunixlib/time/broken.c (working copy)
+@@ -49,7 +49,7 @@
+ #ifdef __TARGET_SCL__
+ -1,
+ #else
+- __locale_territory[LC_TIME],
++ __locale_global.locale_territory[LC_TIME],
+ #endif
+ riscos_time, ordinals);
+ }
+Index: libunixlib/time/gmtime_r.c
+===================================================================
+--- libunixlib/time/gmtime_r.c (revision 7698)
++++ libunixlib/time/gmtime_r.c (working copy)
+@@ -46,7 +46,7 @@
+ #ifdef __TARGET_SCL__
+ -1,
+ #else
+- __locale_territory[LC_TIME],
++ __locale_global.locale_territory[LC_TIME],
+ #endif
+ riscos_time, ordinals)) != NULL)
+ {
+Index: libunixlib/time/localtime_r.c
+===================================================================
+--- libunixlib/time/localtime_r.c (revision 7698)
++++ libunixlib/time/localtime_r.c (working copy)
+@@ -28,7 +28,7 @@
+ #ifdef __TARGET_SCL__
+ -1,
+ #else
+- __locale_territory[LC_TIME],
++ __locale_global.locale_territory[LC_TIME],
+ #endif
+ riscos_time, ordinals)) != NULL)
+ {
+Index: libunixlib/time/mktime.c
+===================================================================
+--- libunixlib/time/mktime.c (revision 7698)
++++ libunixlib/time/mktime.c (working copy)
+@@ -23,7 +23,7 @@
+ #ifdef __TARGET_SCL__
+ -1,
+ #else
+- __locale_territory[LC_TIME],
++ __locale_global.locale_territory[LC_TIME],
+ #endif
+ riscos_time,
+ ordinals)) != NULL)
+Index: libunixlib/time/stdtime.c
+===================================================================
+--- libunixlib/time/stdtime.c (revision 7698)
++++ libunixlib/time/stdtime.c (working copy)
+@@ -48,7 +48,7 @@
+ #ifdef __TARGET_SCL__
+ -1,
+ #else
+- __locale_territory[LC_TIME],
++ __locale_global.locale_territory[LC_TIME],
+ #endif
+ riscos_time,
+ result,
+Index: libunixlib/time/strftime.c
+===================================================================
+--- libunixlib/time/strftime.c (revision 7698)
++++ libunixlib/time/strftime.c (working copy)
+@@ -353,7 +353,7 @@
+ int regs[10];
+ char buffer[64];
+
+- regs[0] = __locale_territory[LC_TIME];
++ regs[0] = __locale_global.locale_territory[LC_TIME];
+ regs[1] = (int)timep;
+ regs[2] = (int)buffer;
+ regs[3] = sizeof (buffer) - 1;
+@@ -368,7 +368,7 @@
+ int regs[10];
+ char buffer[64];
+
+- regs[0] = __locale_territory[LC_TIME];
++ regs[0] = __locale_global.locale_territory[LC_TIME];
+ regs[1] = (int)timep;
+ regs[2] = (int)buffer;
+ regs[3] = sizeof (buffer) - 1;
+Index: libunixlib/time/tzset.c
+===================================================================
+--- libunixlib/time/tzset.c (revision 7698)
++++ libunixlib/time/tzset.c (working copy)
+@@ -36,7 +36,7 @@
+ /* Get timezone information for current territory. */
+ _kernel_swi_regs regs;
+ #ifndef __TARGET_SCL__
+- regs.r[0] = __locale_territory[LC_TIME];
++ regs.r[0] = __locale_global.locale_territory[LC_TIME];
+ #else
+ regs.r[0] = -1; /* Current territory. */
+ #endif
+Index: libunixlib/unix/unix.c
+===================================================================
+--- libunixlib/unix/unix.c (revision 7698)
++++ libunixlib/unix/unix.c (working copy)
+@@ -191,7 +191,7 @@
+ __pthread_prog_init ();
+ __unixlib_signal_initialise (__u);
+ /* Initialise ctype tables to the C locale. */
+- __build_ctype_tables (-2);
++ __build_ctype_tables (&__locale_global, -2);
+ /* Define and initialise the Unix I/O. */
+ initialise_unix_io ();
+ __stdioinit ();
+Index: libunixlib/vscript
+===================================================================
+--- libunixlib/vscript (revision 7698)
++++ libunixlib/vscript (working copy)
+@@ -58,6 +58,9 @@
+ __init_des_r;
+ __init_des;
+ __invalidate;
++ __locale_global;
++ __localeconv_lconv_init;
++ __localeconv_lconv_fini;
+ malloc_trim;
+ malloc_trim_unlocked;
+ malloc_unlocked;
+@@ -80,6 +83,7 @@
+ __res_vinit;
+ __runtime_features;
+ __setup_signalhandler_stack;
++ __setlocale_l;
+ __sdirinit;
+ __sfixinit;
+ __sfixfind;
+Index: libunixlib/wchar/wctype.c
+===================================================================
+--- libunixlib/wchar/wctype.c (revision 7698)
++++ libunixlib/wchar/wctype.c (working copy)
+@@ -4,6 +4,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+ #include <wctype.h>
+
+ int
+@@ -71,3 +72,69 @@
+ {
+ return isxdigit (wc);
+ }
++
++int
++iswalnum_l (wint_t wc, locale_t locale)
++{
++ return isalnum_l (wc, locale);
++}
++
++int
++iswalpha_l (wint_t wc, locale_t locale)
++{
++ return isalpha_l (wc, locale);
++}
++
++int
++iswcntrl_l (wint_t wc, locale_t locale)
++{
++ return iscntrl_l (wc, locale);
++}
++
++int
++iswdigit_l (wint_t wc, locale_t locale)
++{
++ return isdigit_l (wc, locale);
++}
++
++int
++iswgraph_l (wint_t wc, locale_t locale)
++{
++ return isgraph_l (wc, locale);
++}
++
++int
++iswprint_l (wint_t wc, locale_t locale)
++{
++ return isprint_l (wc, locale);
++}
++
++int
++iswpunct_l (wint_t wc, locale_t locale)
++{
++ return ispunct_l (wc, locale);
++}
++
++int
++iswspace_l (wint_t wc, locale_t locale)
++{
++ return isspace_l (wc, locale);
++}
++
++int
++iswxdigit_l (wint_t wc, locale_t locale)
++{
++ return isxdigit_l (wc, locale);
++}
++
++wint_t
++towlower_l (wint_t wc, locale_t locale)
++{
++ return tolower_l (wc, locale);
++}
++
++wint_t
++towupper_l (wint_t wc, locale_t locale)
++{
++ return toupper_l (wc, locale);
++}
+Index: libunixlib/wchar/wmissing.c
+===================================================================
+--- libunixlib/wchar/wmissing.c (revision 7698)
++++ libunixlib/wchar/wmissing.c (working copy)
+@@ -1,7 +1,7 @@
++#include <locale.h>
++#include <stdio.h>
+ #include <stdlib.h>
+ #include <wctype.h>
+-#include <wctype.h>
+-#include <stdio.h>
+
+ int iswupper (wint_t __wc)
+ {
+@@ -9,13 +9,26 @@
+ abort();
+ }
+
+-unsigned long int wcstoul (__const wchar_t *__restrict __nptr,
+- wchar_t **__restrict __endptr, int __base)
++int
++iswupper_l (wint_t wc, locale_t locale)
+ {
+ printf("%s: Not implemented\n", __func__);
+ abort();
+ }
+
++int iswlower (wint_t __wc)
++{
++ printf("%s: Not implemented\n", __func__);
++ abort();
++}
++
++int
++iswlower_l (wint_t wc, locale_t locale)
++{
++ printf("%s: Not implemented\n", __func__);
++ abort();
++}
++
+ int wcscoll (__const wchar_t *__s1, __const wchar_t *__s2)
+ {
+ printf("%s: Not implemented\n", __func__);
+@@ -22,12 +35,47 @@
+ abort();
+ }
+
+-int iswlower (wint_t __wc)
++int wcscoll_l (__const wchar_t *__s1, __const wchar_t *__s2,
++ locale_t loc)
+ {
+ printf("%s: Not implemented\n", __func__);
+ abort();
+ }
+
++int wcscasecmp (__const wchar_t *__s1, __const wchar_t *__s2)
++{
++ printf("%s: Not implemented\n", __func__);
++ abort();
++}
++
++int wcsncasecmp (__const wchar_t *__s1, __const wchar_t *__s2,
++ size_t __n)
++{
++ printf("%s: Not implemented\n", __func__);
++ abort();
++}
++
++int wcscasecmp_l (__const wchar_t *__s1, __const wchar_t *__s2,
++ locale_t __loc)
++{
++ printf("%s: Not implemented\n", __func__);
++ abort();
++}
++
++int wcsncasecmp_l (__const wchar_t *__s1, __const wchar_t *__s2,
++ size_t __n, locale_t __loc)
++{
++ printf("%s: Not implemented\n", __func__);
++ abort();
++}
++
++unsigned long int wcstoul (__const wchar_t *__restrict __nptr,
++ wchar_t **__restrict __endptr, int __base)
++{
++ printf("%s: Not implemented\n", __func__);
++ abort();
++}
++
+ long long int wcstoll (__const wchar_t *__restrict __nptr,
+ wchar_t **__restrict __endptr, int __base)
+ {
+@@ -63,6 +111,13 @@
+ abort();
+ }
+
++size_t wcsxfrm_l (wchar_t *__s1, __const wchar_t *__s2,
++ size_t __n, locale_t __loc)
++{
++ printf("%s: Not implemented\n", __func__);
++ abort();
++}
++
+ float wcstof (__const wchar_t *__restrict __nptr,
+ wchar_t **__restrict __endptr)
+ {
+@@ -83,6 +138,13 @@
+ abort();
+ }
+
++int
++iswblank_l (wint_t __wc, locale_t __locale)
++{
++ printf("%s: Not implemented\n", __func__);
++ abort();
++}
++
+ int iswctype (wint_t __wc, wctype_t __desc)
+ {
+ printf("%s: Not implemented\n", __func__);
+@@ -89,6 +151,12 @@
+ abort();
+ }
+
++int iswctype_l (wint_t __wc, wctype_t __desc, locale_t __locale)
++{
++ printf("%s: Not implemented\n", __func__);
++ abort();
++}
++
+ unsigned long long int wcstoull (__const wchar_t *__restrict __nptr,
+ wchar_t **__restrict __endptr,
+ int __base)
+@@ -116,6 +184,12 @@
+ abort();
+ }
+
++wctype_t wctype_l (__const char *__property, locale_t __locale)
++{
++ printf("%s: Not implemented\n", __func__);
++ abort();
++}
++
+ wint_t ungetwc(wint_t wc, FILE *stream)
+ {
+ printf("%s: Not implemented\n", __func__);
diff --git a/arm-riscos-gnueabihf/recipes/patches/infozip/globals.p b/arm-riscos-gnueabihf/recipes/patches/infozip/globals.p
new file mode 100644
index 0000000..c10adfa
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/patches/infozip/globals.p
@@ -0,0 +1,13 @@
+--- globals.c.orig 2005-03-20 12:32:02.000000000 -0800
++++ globals.c 2008-01-12 22:45:07.000000000 -0800
+@@ -30,6 +30,10 @@
+ int pathput = 1; /* 1=store path with name */
+ #ifdef RISCOS
+ int scanimage = 1; /* 1=scan through image files */
++#else
++#ifdef FORRISCOS
++int decomma = 0;
++#endif
+ #endif
+ int method = BEST; /* one of BEST, DEFLATE (only), or STORE (only) */
+ int dosify = 0; /* 1=make new entries look like MSDOS */
diff --git a/arm-riscos-gnueabihf/recipes/patches/infozip/zip.p b/arm-riscos-gnueabihf/recipes/patches/infozip/zip.p
new file mode 100644
index 0000000..aee2b24
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/patches/infozip/zip.p
@@ -0,0 +1,58 @@
+--- zip.c.orig 2009-05-07 11:54:09.000000000 +0100
++++ zip.c 2009-05-07 11:53:08.000000000 +0100
+@@ -668,6 +668,9 @@
+ ," -h2 show more help -I don't scan thru Image files"
+ #else
+ ," -h2 show more help"
++#ifdef FORRISCOS
++," -, strip ,xxx from filename and convert to RISCOS filetype encoding"
++#endif
+ #endif
+ #endif /* ?MACOS */
+ #ifdef VMS
+@@ -1144,6 +1147,9 @@
+ #if CRYPT && defined(PASSWD_FROM_STDIN)
+ "PASSWD_FROM_STDIN",
+ #endif /* CRYPT & PASSWD_FROM_STDIN */
++#ifdef FORRISCOS
++ "FORRISCOS",
++#endif
+ NULL
+ };
+
+@@ -2109,6 +2115,9 @@
+ #ifdef RISCOS
+ {"/", "exts-to-swap", o_REQUIRED_VALUE, o_NOT_NEGATABLE, '/', "override Zip$Exts"},
+ #endif
++#ifdef FORRISCOS
++ {",", "strip-type", o_NO_VALUE, o_NOT_NEGATABLE, ',', "strip ,xxx extension"},
++#endif
+ /* the end of the list */
+ {NULL, NULL, o_NO_VALUE, o_NOT_NEGATABLE, 0, NULL} /* end has option_ID = 0 */
+ };
+@@ -2847,6 +2856,12 @@
+ case 'I': /* Don't scan through Image files */
+ scanimage = 0;
+ break;
++#else
++#ifdef FORRISCOS
++ case ',': /* Convert ,xxx to RISC OS extended filetype info */
++ decomma = 1;
++ break;
++#endif
+ #endif
+ #ifdef MACOS
+ case o_jj: /* store absolute path including volname */
+--- zip.h.org 2008-01-12 22:56:51.000000000 -0800
++++ zip.h 2008-01-12 23:00:05.000000000 -0800
+@@ -323,6 +323,10 @@
+
+ #ifdef RISCOS
+ extern int scanimage; /* Scan through image files */
++#else
++#ifdef FORRISCOS
++extern int decomma; /* Convert ,xxx filename to RISC OS filetype info */
++#endif
+ #endif
+
+ #define BEST -1 /* Use best method (deflation or store) */
diff --git a/arm-riscos-gnueabihf/recipes/patches/infozip/zipup.p b/arm-riscos-gnueabihf/recipes/patches/infozip/zipup.p
new file mode 100644
index 0000000..f4d43d0
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/patches/infozip/zipup.p
@@ -0,0 +1,162 @@
+--- zipup.c.orig 2008-01-12 22:29:14.000000000 -0800
++++ zipup.c 2008-01-12 22:36:00.000000000 -0800
+@@ -139,6 +139,9 @@
+ #else
+ local int filetypes OF((char *, char *));
+ #endif
++#ifdef FORRISCOS
++ local int set_extra_field_forriscos OF((struct zlist far *z, iztimes *z_utim));
++#endif
+ local unsigned file_read OF((char *buf, unsigned size));
+ #ifdef USE_ZLIB
+ local int zl_deflate_init OF((int pack_level));
+@@ -379,7 +382,133 @@
+ }
+ #endif /* ?RISCOS */
+
++#ifdef FORRISCOS
++
++int set_extra_field_forriscos(z, z_utim)
++ struct zlist far *z;
++ iztimes *z_utim;
++{
++#ifdef USE_EF_UT_TIME
++ char *eb_ptr;
++#endif /* USE_EF_UT_TIME */
++ char *cptr;
++ char *extra_block;
++ unsigned int addr;
++ unsigned int ftype = 0xfff; /* Untyped files default to 'text' */
++ unsigned timlo; /* 3 lower bytes of acorn file-time plus carry byte */
++ unsigned timhi; /* 2 high bytes of acorn file-time */
++
++#define EB_SPARK_LEN 20
++#define EB_SPARK_SIZE (EB_HEADSIZE+EB_SPARK_LEN)
++#ifdef USE_EF_UT_TIME
++# ifdef IZ_CHECK_TZ
++# define EB_UTTIME_SIZE (zp_tz_is_valid ? EB_HEADSIZE+EB_UT_LEN(1) : 0)
++# else
++# define EB_UTTIME_SIZE (EB_HEADSIZE+EB_UT_LEN(1))
++# endif
++#else
++# define EB_UTTIME_SIZE 0
++#endif
++#define EF_SPARK_TOTALSIZE (EB_SPARK_SIZE + EB_UTTIME_SIZE)
++
++ cptr=strrchr(z->iname, (int) ',');
++ if (cptr)
++ if ((cptr - z->iname) != (int)(strlen(z->iname)-4))
++ cptr = NULL; /* There was a comma, but it wasn't a ,xxx at the end! */
++
++ if (cptr)
++ {
++ *cptr='\0'; /* Chop the filename at the comma */
++
++ ftype = strtol(cptr+1, NULL, 16); /* read the ,xxx as hex filetype */
++ }
++ else
++ {
++ /* When there is no given filetype, but there is a full stop in the name,
++ then it is better to let the unzip utility in RISC OS do a MimeMap lookup
++ instead, and therefore do nothing here */
++ if (strchr(z->iname, '.'))
++ return ZE_OK;
++ }
++
++ z->extra=(char *)malloc(EF_SPARK_TOTALSIZE);
++ if (z->extra==NULL) {
++ fprintf(stderr," set_extra_field_forriscos: not enough memory\n");
++ return ZE_MEM;
++ }
++ z->cextra = z->extra;
++ z->cext = z->ext = EF_SPARK_TOTALSIZE;
++
++ timlo = ((unsigned)z_utim->mtime & 0x00ffffffU) * 100 + 0x00996a00U;
++ timhi = ((unsigned)z_utim->mtime >> 24);
++ timhi = timhi * 100 + 0x0000336eU + (timlo >> 24);
++
++ extra_block=z->extra;
++ /* ID */
++ extra_block[0]='A';
++ extra_block[1]='C';
++
++ /* size */
++ extra_block[2]=(char)(EB_SPARK_LEN);
++ extra_block[3]=(char)(EB_SPARK_LEN)>>8;
++
++ /* ID_2 */
++ extra_block[4]='A';
++ extra_block[5]='R';
++ extra_block[6]='C';
++ extra_block[7]='0';
++
++ /* Load address */
++ addr=0xfff00000 | (ftype << 8); /* This file is typed, and has filetype 'ftype' */
++ addr|= ((timhi >> 8) & 0xffU);
++ extra_block[8]=(char)(addr);
++ extra_block[9]=(char)(addr>>8);
++ extra_block[10]=(char)(addr>>16);
++ extra_block[11]=(char)(addr>>24);
++
++ /* Exec address */
++ addr=(timlo & 0x00ffffffU) | ((timhi & 0x000000ffU) << 24);
++ extra_block[12]=(char)(addr);
++ extra_block[13]=(char)(addr>>8);
++ extra_block[14]=(char)(addr>>16);
++ extra_block[15]=(char)(addr>>24);
++
++ /* Attributes */
++ extra_block[16]=0x13; /* Private read/write, no public access, unlocked */
++ extra_block[17]=0;
++ extra_block[18]=0;
++ extra_block[19]=0;
++
++ /* Zero */
++ extra_block[20]=0;
++ extra_block[21]=0;
++ extra_block[22]=0;
++ extra_block[23]=0;
++
++#ifdef USE_EF_UT_TIME
++# ifdef IZ_CHECK_TZ
++ if (zp_tz_is_valid) {
++# endif
++ eb_ptr = z->extra + EB_SPARK_SIZE;
++
++ eb_ptr[0] = 'U';
++ eb_ptr[1] = 'T';
++ eb_ptr[2] = EB_UT_LEN(1); /* length of data part of e.f. */
++ eb_ptr[3] = 0;
++ eb_ptr[4] = EB_UT_FL_MTIME;
++ eb_ptr[5] = (char)(z_utim->mtime);
++ eb_ptr[6] = (char)(z_utim->mtime >> 8);
++ eb_ptr[7] = (char)(z_utim->mtime >> 16);
++ eb_ptr[8] = (char)(z_utim->mtime >> 24);
++# ifdef IZ_CHECK_TZ
++ }
++# endif
++#endif /* USE_EF_UT_TIME */
++
++ return ZE_OK;
++}
+
++#endif /* FORRISCOS */
+
+ /* Note: a zip "entry" includes a local header (which includes the file
+ name), an encryption header if encrypting, the compressed data
+@@ -552,6 +681,15 @@
+ #if !(defined(VMS) && defined(VMS_PK_EXTRA))
+ if (extra_fields) {
+ /* create extra field and change z->att and z->atx if desired */
++#ifdef FORRISCOS
++ if (decomma)
++ {
++ /* If we're making a zip for RISC OS, we don't bother with any other */
++ /* OS-Specific info (although we could - but there's no point!) */
++ set_extra_field_forriscos(z, &f_utim);
++ }
++ else
++#endif
+ set_extra_field(z, &f_utim);
+ # ifdef QLZIP
+ if(qlflag)
diff --git a/arm-riscos-gnueabihf/recipes/patches/oslib/vapi.p b/arm-riscos-gnueabihf/recipes/patches/oslib/vapi.p
new file mode 100644
index 0000000..a3daf40
--- /dev/null
+++ b/arm-riscos-gnueabihf/recipes/patches/oslib/vapi.p
@@ -0,0 +1,10 @@
+--- Tools/DefMod2/vapi.c.orig 2017-09-19 11:57:15.559547484 +0100
++++ Tools/DefMod2/vapi.c 2017-09-19 11:57:31.067750029 +0100
+@@ -23,6 +23,7 @@
+ #include <stdio.h>
+ #include <string.h>
+ #include <ctype.h>
++#include <stdbool.h>
+
+ #include "oslib/os.h"
+
-----------------------------------------------------------------------
Summary of changes:
sdk/Makefile | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/sdk/Makefile b/sdk/Makefile
index af66884..a8dda57 100644
--- a/sdk/Makefile
+++ b/sdk/Makefile
@@ -25,25 +25,25 @@ endif
# Upstream package versions
# https://zlib.net/
-VERSION_ZLIB := 1.2.12
+VERSION_ZLIB := 1.2.13
# https://www.gnu.org/software/libiconv/
VERSION_LIBICONV := 1.17
# https://laurikari.net/tre/
VERSION_LIBTRE := 0.8.0
# https://www.openssl.org/
-VERSION_OPENSSL := 3.0.3
+VERSION_OPENSSL := 3.0.7
# http://www.libpng.org/pub/png/libpng.html
-VERSION_LIBPNG := 1.6.37
+VERSION_LIBPNG := 1.6.38
# http://libjpeg.sourceforge.net/
VERSION_LIBJPEG := 8d
# https://libjpeg-turbo.org/
-VERSION_LIBJPEG_TURBO := 2.1.3
+VERSION_LIBJPEG_TURBO := 2.1.4
# https://developers.google.com/speed/webp/
-VERSION_LIBWEBP := 1.2.2
+VERSION_LIBWEBP := 1.2.4
# https://c-ares.haxx.se/
VERSION_LIBCARES := 1.18.1
# https://curl.haxx.se/
-VERSION_LIBCURL := 7.83.1
+VERSION_LIBCURL := 7.86.0
VERSION_LIBGNURX := 2.5.1
# http://mission-base.com/peter/source/
# 1.7.0: https://github.com/peterGraf/pbl/releases
@@ -51,7 +51,7 @@ VERSION_LIBPBL := 1_04
# Git-20170304
VERSION_LIBCF := CVS-20130415
# https://github.com/libexpat/libexpat
-VERSION_LIBEXPAT := 2.4.8
+VERSION_LIBEXPAT := 2.5.0
VERSION_LDG := 2.35
VERSION_WINDOM := 2.0.1
# https://github.com/berkus/hermes-pixel-format/archive/refs/tags/v1.3.3.ta...
--
Cross-compilation toolchains and environments
4 months, 3 weeks
toolchains: branch master updated. 2bbddd7aaabeae11c1862787ef6f99b3b816324a
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/toolchains.git/shortlog/2bbddd7aaabeae11c1...
...commit http://git.netsurf-browser.org/toolchains.git/commit/2bbddd7aaabeae11c186...
...tree http://git.netsurf-browser.org/toolchains.git/tree/2bbddd7aaabeae11c18627...
The branch, master has been updated
via 2bbddd7aaabeae11c1862787ef6f99b3b816324a (commit)
from db19136aaabca03642d4d79facf70e567a3c2536 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=2bbddd7aaabeae11...
commit 2bbddd7aaabeae11c1862787ef6f99b3b816324a
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
SDK: bump library versions
diff --git a/sdk/Makefile b/sdk/Makefile
index 75ee28d..1cc3418 100644
--- a/sdk/Makefile
+++ b/sdk/Makefile
@@ -24,7 +24,7 @@ endif
# Upstream package versions
# https://zlib.net/
-VERSION_ZLIB := 1.2.12
+VERSION_ZLIB := 1.2.13
# https://www.gnu.org/software/libiconv/
VERSION_LIBICONV := 1.17
# https://laurikari.net/tre/
@@ -32,17 +32,17 @@ VERSION_LIBTRE := 0.8.0
# https://www.openssl.org/
VERSION_OPENSSL := 3.0.7
# http://www.libpng.org/pub/png/libpng.html
-VERSION_LIBPNG := 1.6.37
+VERSION_LIBPNG := 1.6.38
# http://libjpeg.sourceforge.net/
VERSION_LIBJPEG := 8d
# https://libjpeg-turbo.org/
-VERSION_LIBJPEG_TURBO := 2.1.3
+VERSION_LIBJPEG_TURBO := 2.1.4
# https://developers.google.com/speed/webp/
-VERSION_LIBWEBP := 1.2.2
+VERSION_LIBWEBP := 1.2.4
# https://c-ares.haxx.se/
VERSION_LIBCARES := 1.18.1
# https://curl.haxx.se/
-VERSION_LIBCURL := 7.83.1
+VERSION_LIBCURL := 7.86.0
VERSION_LIBGNURX := 2.5.1
# http://mission-base.com/peter/source/
# 1.7.0: https://github.com/peterGraf/pbl/releases
@@ -50,7 +50,7 @@ VERSION_LIBPBL := 1_04
# Git-20170304
VERSION_LIBCF := CVS-20130415
# https://github.com/libexpat/libexpat
-VERSION_LIBEXPAT := 2.4.8
+VERSION_LIBEXPAT := 2.5.0
VERSION_LDG := 2.35
VERSION_WINDOM := 2.0.1
# https://github.com/berkus/hermes-pixel-format/archive/refs/tags/v1.3.3.ta...
-----------------------------------------------------------------------
Summary of changes:
sdk/Makefile | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/sdk/Makefile b/sdk/Makefile
index 75ee28d..1cc3418 100644
--- a/sdk/Makefile
+++ b/sdk/Makefile
@@ -24,7 +24,7 @@ endif
# Upstream package versions
# https://zlib.net/
-VERSION_ZLIB := 1.2.12
+VERSION_ZLIB := 1.2.13
# https://www.gnu.org/software/libiconv/
VERSION_LIBICONV := 1.17
# https://laurikari.net/tre/
@@ -32,17 +32,17 @@ VERSION_LIBTRE := 0.8.0
# https://www.openssl.org/
VERSION_OPENSSL := 3.0.7
# http://www.libpng.org/pub/png/libpng.html
-VERSION_LIBPNG := 1.6.37
+VERSION_LIBPNG := 1.6.38
# http://libjpeg.sourceforge.net/
VERSION_LIBJPEG := 8d
# https://libjpeg-turbo.org/
-VERSION_LIBJPEG_TURBO := 2.1.3
+VERSION_LIBJPEG_TURBO := 2.1.4
# https://developers.google.com/speed/webp/
-VERSION_LIBWEBP := 1.2.2
+VERSION_LIBWEBP := 1.2.4
# https://c-ares.haxx.se/
VERSION_LIBCARES := 1.18.1
# https://curl.haxx.se/
-VERSION_LIBCURL := 7.83.1
+VERSION_LIBCURL := 7.86.0
VERSION_LIBGNURX := 2.5.1
# http://mission-base.com/peter/source/
# 1.7.0: https://github.com/peterGraf/pbl/releases
@@ -50,7 +50,7 @@ VERSION_LIBPBL := 1_04
# Git-20170304
VERSION_LIBCF := CVS-20130415
# https://github.com/libexpat/libexpat
-VERSION_LIBEXPAT := 2.4.8
+VERSION_LIBEXPAT := 2.5.0
VERSION_LDG := 2.35
VERSION_WINDOM := 2.0.1
# https://github.com/berkus/hermes-pixel-format/archive/refs/tags/v1.3.3.ta...
--
Cross-compilation toolchains and environments
4 months, 3 weeks
toolchains: branch jmb/arm-riscos-gnueabihf updated. 6a0e3141ee021b4867a39269c77fe26beb058534
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/toolchains.git/shortlog/6a0e3141ee021b4867...
...commit http://git.netsurf-browser.org/toolchains.git/commit/6a0e3141ee021b4867a3...
...tree http://git.netsurf-browser.org/toolchains.git/tree/6a0e3141ee021b4867a392...
The branch, jmb/arm-riscos-gnueabihf has been updated
via 6a0e3141ee021b4867a39269c77fe26beb058534 (commit)
from 0c7fc8e52cefbe787bc5f33dcc9ae95ef3a5247c (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/toolchains.git/commit/?id=6a0e3141ee021b48...
commit 6a0e3141ee021b4867a39269c77fe26beb058534
Author: John-Mark Bell <jmb(a)netsurf-browser.org>
Commit: John-Mark Bell <jmb(a)netsurf-browser.org>
SDK/arm-unknown-riscos: poke function names
diff --git a/sdk/Makefile b/sdk/Makefile
index aa89519..af66884 100644
--- a/sdk/Makefile
+++ b/sdk/Makefile
@@ -77,6 +77,10 @@ pkg_config_libdir__ := $(GCCSDK_INSTALL_ENV)/lib/pkgconfig
# Target
TARGET := $(shell $(cc__) -dumpmachine)
+ifeq ($(findstring -riscos,$(TARGET)),-riscos)
+ cflags__ := $(cflags__) -mpoke-function-name
+endif
+
# Environment
# Newer autotools objects to -I appearing in CFLAGS
cleanenv := PATH="$(path__)" CC="$(cc__)" CXX="$(cxx__)" AR="$(ar__)" RANLIB="$(ranlib__)" CPPFLAGS="$(cppflags__)" LDFLAGS="$(ldflags__)" PKG_CONFIG_LIBDIR="$(pkg_config_libdir__)"
-----------------------------------------------------------------------
Summary of changes:
sdk/Makefile | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/sdk/Makefile b/sdk/Makefile
index aa89519..af66884 100644
--- a/sdk/Makefile
+++ b/sdk/Makefile
@@ -77,6 +77,10 @@ pkg_config_libdir__ := $(GCCSDK_INSTALL_ENV)/lib/pkgconfig
# Target
TARGET := $(shell $(cc__) -dumpmachine)
+ifeq ($(findstring -riscos,$(TARGET)),-riscos)
+ cflags__ := $(cflags__) -mpoke-function-name
+endif
+
# Environment
# Newer autotools objects to -I appearing in CFLAGS
cleanenv := PATH="$(path__)" CC="$(cc__)" CXX="$(cxx__)" AR="$(ar__)" RANLIB="$(ranlib__)" CPPFLAGS="$(cppflags__)" LDFLAGS="$(ldflags__)" PKG_CONFIG_LIBDIR="$(pkg_config_libdir__)"
--
Cross-compilation toolchains and environments
4 months, 3 weeks