diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/internal/slibtool_driver_impl.h | 12 | ||||
-rw-r--r-- | src/util/slbt_create_mapfile.c | 127 |
2 files changed, 139 insertions, 0 deletions
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); +} |