Blame src/arbits/slbt_archive_mapfile.c

a740e6
/*******************************************************************/
a740e6
/*  slibtool: a skinny libtool implementation, written in C        */
a740e6
/*  Copyright (C) 2016--2024  SysDeer Technologies, LLC            */
a740e6
/*  Released under the Standard MIT License; see COPYING.SLIBTOOL. */
a740e6
/*******************************************************************/
a740e6
a740e6
#include <time.h>
a740e6
#include <locale.h>
a740e6
#include <regex.h>
a740e6
#include <inttypes.h>
a740e6
#include <slibtool/slibtool.h>
a740e6
#include <slibtool/slibtool_output.h>
a740e6
#include "slibtool_driver_impl.h"
a740e6
#include "slibtool_dprintf_impl.h"
a740e6
#include "slibtool_errinfo_impl.h"
a740e6
#include "slibtool_ar_impl.h"
a740e6
e19ed2
/********************************************************/
e19ed2
/* Generate a symbol mapfile (aka version script) that  */
e19ed2
/* could be passed to the host linker.                  */
e19ed2
/*                                                      */
e19ed2
/* Since the symbol list is directly derived from the   */
e19ed2
/* archive's armap member, prepending symbol names with */
e19ed2
/* an underscore (where relevant) is not necessary.     */
e19ed2
/********************************************************/
e19ed2
403e07
static int slbt_is_strong_coff_symbol(const char * sym)
403e07
{
c62c8b
	return strncmp(sym,"__imp_",6)
c62c8b
		&& strncmp(sym,".weak.",6)
c62c8b
		&& strncmp(sym,".refptr.",8);
403e07
}
403e07
551fc3
static int slbt_ar_output_mapfile_impl(
a740e6
	const struct slbt_driver_ctx *  dctx,
a740e6
	struct slbt_archive_meta_impl * mctx,
14302e
	int                             fdout)
a740e6
{
df2627
	bool            fsort;
9feb47
	bool            fcoff;
e19ed2
	bool            fmach;
a740e6
	const char *    regex;
a740e6
	const char **   symv;
df2627
	const char **   symstrv;
a740e6
	regex_t         regctx;
5ade20
	regmatch_t      pmatch[2] = {{0,0},{0,0}};
a740e6
874b59
	fsort = !(dctx->cctx->fmtflags & SLBT_OUTPUT_ARCHIVE_NOSORT);
df2627
b8dd56
	fmach  = slbt_host_objfmt_is_macho(dctx);
b8dd56
	fmach |= (mctx->ofmtattr & AR_OBJECT_ATTR_MACHO);
b8dd56
b8dd56
	fcoff  = slbt_host_objfmt_is_coff(dctx);
b8dd56
	fcoff |= (mctx->ofmtattr & AR_OBJECT_ATTR_COFF);
e19ed2
e19ed2
	if (fcoff) {
e19ed2
		if (slbt_dprintf(fdout,"EXPORTS\n") < 0)
e19ed2
			return SLBT_SYSTEM_ERROR(dctx,0);
e19ed2
	} else if (fmach) {
e19ed2
		if (slbt_dprintf(fdout,"# export_list, armap underscores\n") < 0)
e19ed2
			return SLBT_SYSTEM_ERROR(dctx,0);
e19ed2
	} else {
e19ed2
		if (slbt_dprintf(fdout,"{\n" "\t" "global:\n") < 0)
e19ed2
			return SLBT_SYSTEM_ERROR(dctx,0);
e19ed2
	}
a740e6
df2627
	if (fsort && !mctx->mapstrv)
df2627
		if (slbt_update_mapstrv(dctx,mctx) < 0)
df2627
			return SLBT_NESTED_ERROR(dctx);
df2627
a740e6
	if ((regex = dctx->cctx->regex))
a740e6
		if (regcomp(&regctx,regex,REG_NEWLINE))
a740e6
			return SLBT_CUSTOM_ERROR(
a740e6
				dctx,
a740e6
				SLBT_ERR_FLOW_ERROR);
a740e6
df2627
	symstrv = fsort ? mctx->mapstrv : mctx->symstrv;
df2627
e19ed2
	for (symv=symstrv; *symv; symv++) {
403e07
		if (!fcoff || slbt_is_strong_coff_symbol(*symv)) {
e19ed2
			if (!regex || !regexec(&regctx,*symv,1,pmatch,0)) {
e19ed2
				if (fcoff || fmach) {
e19ed2
					if (slbt_dprintf(fdout,"%s\n",*symv) < 0)
e19ed2
						return SLBT_SYSTEM_ERROR(dctx,0);
e19ed2
				} else {
e19ed2
					if (slbt_dprintf(fdout,"\t\t%s;\n",*symv) < 0)
e19ed2
						return SLBT_SYSTEM_ERROR(dctx,0);
e19ed2
				}
e19ed2
			}
e19ed2
		}
e19ed2
	}
a740e6
a740e6
	if (regex)
a740e6
		regfree(&regctx);
a740e6
e19ed2
	if (!fcoff && !fmach)
e19ed2
		if (slbt_dprintf(fdout,"\n\t" "local:\n" "\t\t*;\n" "};\n") < 0)
e19ed2
			return SLBT_SYSTEM_ERROR(dctx,0);
a740e6
a740e6
	return 0;
a740e6
}
a740e6
14302e
51c276
static int slbt_ar_create_mapfile_impl(
14302e
	const struct slbt_archive_meta *  meta,
14302e
	const char *                      path,
14302e
	mode_t                            mode)
a740e6
{
7cfae7
	int                             ret;
a740e6
	struct slbt_archive_meta_impl * mctx;
a740e6
	const struct slbt_driver_ctx *  dctx;
a740e6
	struct slbt_fd_ctx              fdctx;
14302e
	int                             fdout;
a740e6
a740e6
	mctx = slbt_archive_meta_ictx(meta);
a740e6
	dctx = (slbt_archive_meta_ictx(meta))->dctx;
a740e6
ea4137
	if (slbt_lib_get_driver_fdctx(dctx,&fdctx) < 0)
a740e6
		return SLBT_NESTED_ERROR(dctx);
a740e6
a740e6
	if (!meta->a_memberv)
a740e6
		return 0;
a740e6
14302e
	if (path) {
14302e
		if ((fdout = openat(
14302e
				fdctx.fdcwd,path,
14302e
				O_WRONLY|O_CREAT|O_TRUNC,
14302e
				mode)) < 0)
14302e
			return SLBT_SYSTEM_ERROR(dctx,0);
14302e
	} else {
14302e
		fdout = fdctx.fdout;
14302e
	}
14302e
7cfae7
	ret = slbt_ar_output_mapfile_impl(
14302e
		dctx,mctx,fdout);
7cfae7
7cfae7
	if (path) {
7cfae7
		close(fdout);
7cfae7
	}
7cfae7
7cfae7
	return ret;
14302e
}
14302e
14302e
51c276
int slbt_ar_create_mapfile(
14302e
	const struct slbt_archive_meta *  meta,
14302e
	const char *                      path,
14302e
	mode_t                            mode)
14302e
{
51c276
	return slbt_ar_create_mapfile_impl(meta,path,mode);
a740e6
}