diff options
-rw-r--r-- | include/slibtool/slibtool.h | 2 | ||||
-rw-r--r-- | project/common.mk | 1 | ||||
-rw-r--r-- | src/internal/slibtool_driver_impl.h | 12 | ||||
-rw-r--r-- | src/util/slbt_create_mapfile.c | 127 |
4 files changed, 142 insertions, 0 deletions
diff --git a/include/slibtool/slibtool.h b/include/slibtool/slibtool.h index d80a00e..38d47a0 100644 --- a/include/slibtool/slibtool.h +++ b/include/slibtool/slibtool.h @@ -390,6 +390,8 @@ slbt_api int slbt_host_flavor_settings (const char *, const struct slbt_flavor_ slbt_api int slbt_util_import_archive (const struct slbt_driver_ctx *, struct slbt_exec_ctx *, char * dstarchive, char * srcarchive); +slbt_api int slbt_util_create_mapfile (const struct slbt_symlist_ctx *, const char *, mode_t); + slbt_api int slbt_util_copy_file (const struct slbt_driver_ctx *, struct slbt_exec_ctx *, char * src, char * dst); diff --git a/project/common.mk b/project/common.mk index 433711f..fbd81fd 100644 --- a/project/common.mk +++ b/project/common.mk @@ -21,6 +21,7 @@ API_SRCS = \ src/driver/slbt_version_info.c \ src/host/slbt_host_params.c \ src/util/slbt_archive_import.c \ + src/util/slbt_create_mapfile.c \ src/util/slbt_copy_file.c \ src/util/slbt_dump_machine.c \ src/util/slbt_map_input.c \ diff --git a/src/internal/slibtool_driver_impl.h b/src/internal/slibtool_driver_impl.h index 8420532..5bc421d 100644 --- a/src/internal/slibtool_driver_impl.h +++ b/src/internal/slibtool_driver_impl.h @@ -320,6 +320,18 @@ static inline struct slbt_driver_ctx_impl * slbt_get_driver_ictx(const struct sl return 0; } +static inline struct slbt_symlist_ctx_impl * slbt_get_symlist_ictx(const struct slbt_symlist_ctx * sctx) +{ + uintptr_t addr; + + if (sctx) { + addr = (uintptr_t)sctx - offsetof(struct slbt_symlist_ctx_impl,sctx); + return (struct slbt_symlist_ctx_impl *)addr; + } + + return 0; +} + static inline void slbt_driver_set_arctx( const struct slbt_driver_ctx * dctx, const struct slbt_archive_ctx * arctx, diff --git a/src/util/slbt_create_mapfile.c b/src/util/slbt_create_mapfile.c new file mode 100644 index 0000000..d0f5d95 --- /dev/null +++ b/src/util/slbt_create_mapfile.c @@ -0,0 +1,127 @@ +/*******************************************************************/ +/* slibtool: a skinny libtool implementation, written in C */ +/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */ +/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ +/*******************************************************************/ + +#include <time.h> +#include <locale.h> +#include <regex.h> +#include <inttypes.h> +#include <slibtool/slibtool.h> +#include <slibtool/slibtool_output.h> +#include "slibtool_driver_impl.h" +#include "slibtool_dprintf_impl.h" +#include "slibtool_errinfo_impl.h" +#include "slibtool_ar_impl.h" + +/****************************************************/ +/* Generate a linker version script (aka mapfile) */ +/* that could be passed to the host linker. */ +/* */ +/* Since the provided symbol list is host-neautral, */ +/* prepend symbol names with an underscore whenever */ +/* necessary. */ +/****************************************************/ + +static int slbt_is_strong_coff_symbol(const char * sym) +{ + return strncmp(sym,"__imp_",6) && strncmp(sym,".weak.",6); +} + +static int slbt_util_output_mapfile_impl( + const struct slbt_driver_ctx * dctx, + const struct slbt_symlist_ctx * sctx, + int fdout) +{ + bool fcoff; + bool fmach; + const char ** symv; + const char ** symstrv; + + fmach = !strcmp(dctx->cctx->host.flavor,"darwin"); + + fcoff = !strcmp(dctx->cctx->host.flavor,"midipix"); + fcoff = fcoff || !strcmp(dctx->cctx->host.flavor,"cygwin"); + fcoff = fcoff || !strcmp(dctx->cctx->host.flavor,"mingw"); + fcoff = fcoff || !strcmp(dctx->cctx->host.flavor,"msys2"); + + if (fcoff) { + if (slbt_dprintf(fdout,"EXPORTS\n") < 0) + return SLBT_SYSTEM_ERROR(dctx,0); + } else if (fmach) { + if (slbt_dprintf(fdout,"# export_list, underscores prepended\n") < 0) + return SLBT_SYSTEM_ERROR(dctx,0); + } else { + if (slbt_dprintf(fdout,"{\n" "\t" "global:\n") < 0) + return SLBT_SYSTEM_ERROR(dctx,0); + } + + symstrv = sctx->symstrv; + + for (symv=symstrv; *symv; symv++) { + if (!fcoff || slbt_is_strong_coff_symbol(*symv)) { + if (fcoff) { + if (slbt_dprintf(fdout,"%s\n",*symv) < 0) + return SLBT_SYSTEM_ERROR(dctx,0); + } else if (fmach) { + if (slbt_dprintf(fdout,"_%s\n",*symv) < 0) + return SLBT_SYSTEM_ERROR(dctx,0); + } else { + if (slbt_dprintf(fdout,"\t\t%s;\n",*symv) < 0) + return SLBT_SYSTEM_ERROR(dctx,0); + } + } + } + + if (!fcoff && !fmach) + if (slbt_dprintf(fdout,"\n\t" "local:\n" "\t\t*;\n" "};\n") < 0) + return SLBT_SYSTEM_ERROR(dctx,0); + + return 0; +} + + +static int slbt_util_create_mapfile_impl( + const struct slbt_symlist_ctx * sctx, + const char * path, + mode_t mode) +{ + int ret; + const struct slbt_driver_ctx * dctx; + struct slbt_fd_ctx fdctx; + int fdout; + + dctx = (slbt_get_symlist_ictx(sctx))->dctx; + + if (slbt_lib_get_driver_fdctx(dctx,&fdctx) < 0) + return SLBT_NESTED_ERROR(dctx); + + if (path) { + if ((fdout = openat( + fdctx.fdcwd,path, + O_WRONLY|O_CREAT|O_TRUNC, + mode)) < 0) + return SLBT_SYSTEM_ERROR(dctx,0); + } else { + fdout = fdctx.fdout; + } + + ret = slbt_util_output_mapfile_impl( + dctx,sctx,fdout); + + if (path) { + close(fdout); + } + + return ret; +} + + +int slbt_util_create_mapfile( + const struct slbt_symlist_ctx * sctx, + const char * path, + mode_t mode) +{ + return slbt_util_create_mapfile_impl(sctx,path,mode); +} |