Blame src/arbits/output/slbt_au_output_symbols.c

d9285e
/*******************************************************************/
eac61a
/*  slibtool: a strong libtool implementation, written in C        */
d9285e
/*  Copyright (C) 2016--2024  SysDeer Technologies, LLC            */
d9285e
/*  Released under the Standard MIT License; see COPYING.SLIBTOOL. */
d9285e
/*******************************************************************/
d9285e
d9285e
#include <time.h>
d9285e
#include <locale.h>
76c5e9
#include <regex.h>
d9285e
#include <inttypes.h>
d9285e
#include <slibtool/slibtool.h>
d9285e
#include <slibtool/slibtool_output.h>
d9285e
#include "slibtool_driver_impl.h"
d9285e
#include "slibtool_dprintf_impl.h"
d9285e
#include "slibtool_errinfo_impl.h"
279932
#include "slibtool_pecoff_impl.h"
41a868
#include "slibtool_tmpfile_impl.h"
d9285e
#include "slibtool_ar_impl.h"
d9285e
d9285e
#define SLBT_PRETTY_FLAGS       (SLBT_PRETTY_YAML      \
d9285e
	                         | SLBT_PRETTY_POSIX    \
d9285e
	                         | SLBT_PRETTY_HEXDATA)
d9285e
3fa3e3
static int slbt_au_output_symbols_posix(
d9285e
	const struct slbt_driver_ctx *  dctx,
d9285e
	struct slbt_archive_meta_impl * mctx,
73a403
	int                             fdout)
d9285e
{
df2627
	bool            fsort;
9feb47
	bool            fcoff;
1443eb
	const char *    dot;
1443eb
	const char *    mark;
76c5e9
	const char *    regex;
d9285e
	const char **   symv;
df2627
	const char **   symstrv;
76c5e9
	regex_t         regctx;
5ade20
	regmatch_t      pmatch[2] = {{0,0},{0,0}};
1443eb
	char            strbuf[4096];
d9285e
874b59
	fsort = !(dctx->cctx->fmtflags & SLBT_OUTPUT_ARCHIVE_NOSORT);
db80f8
	fcoff = (mctx->ofmtattr & AR_OBJECT_ATTR_COFF);
df2627
df2627
	if (fsort && !mctx->mapstrv)
df2627
		if (slbt_update_mapstrv(dctx,mctx) < 0)
df2627
			return SLBT_NESTED_ERROR(dctx);
d9285e
76c5e9
	if ((regex = dctx->cctx->regex))
1ca669
		if (regcomp(&regctx,regex,REG_EXTENDED|REG_NEWLINE))
76c5e9
			return SLBT_CUSTOM_ERROR(
76c5e9
				dctx,
76c5e9
				SLBT_ERR_FLOW_ERROR);
76c5e9
df2627
	symstrv = fsort ? mctx->mapstrv : mctx->symstrv;
df2627
1443eb
	for (symv=symstrv; *symv; symv++) {
1443eb
		if (!fcoff || slbt_is_strong_coff_symbol(*symv)) {
1443eb
			if (!regex || !regexec(&regctx,*symv,1,pmatch,0)) {
9feb47
				if (slbt_dprintf(fdout,"%s\n",*symv) < 0)
9feb47
					return SLBT_SYSTEM_ERROR(dctx,0);
1443eb
			}
1443eb
1443eb
		/* coff weak symbols: expsym = .weak.alias.strong */
1443eb
		} else if (fcoff && !strncmp(*symv,".weak.",6)) {
1443eb
			mark = &(*symv)[6];
1443eb
			dot  = strchr(mark,'.');
1443eb
1443eb
			strncpy(strbuf,mark,dot-mark);
1443eb
			strbuf[dot-mark] = '\0';
1443eb
1443eb
			if (!regex || !regexec(&regctx,strbuf,1,pmatch,0))
1443eb
				if (slbt_dprintf(fdout,"%s\n",strbuf) < 0)
1443eb
					return SLBT_SYSTEM_ERROR(dctx,0);
1443eb
		}
1443eb
	}
76c5e9
76c5e9
	if (regex)
76c5e9
		regfree(&regctx);
d9285e
d9285e
	return 0;
d9285e
}
d9285e
41a868
static int slbt_au_output_one_symbol_yaml(
41a868
	int                             fdout,
41a868
	struct slbt_archive_meta_impl * mctx,
41a868
	const char *                    symname)
41a868
{
41a868
	struct ar_meta_symbol_info **   syminfv;
41a868
41a868
	for (syminfv=mctx->syminfv; *syminfv; syminfv++)
41a868
		if (!strcmp(syminfv[0]->ar_symbol_name,symname))
41a868
			return slbt_dprintf(
41a868
				fdout,
41a868
				"    - Symbol:\n"
41a868
				"      - [ object_name: " "%s"    " ]\n"
41a868
				"      - [ symbol_name: " "%s"    " ]\n"
41a868
				"      - [ symbol_type: " "%s"    " ]\n\n",
41a868
				syminfv[0]->ar_object_name,
41a868
				symname,
41a868
				syminfv[0]->ar_symbol_type);
41a868
41a868
	return 0;
41a868
}
41a868
3fa3e3
static int slbt_au_output_symbols_yaml(
d9285e
	const struct slbt_driver_ctx *  dctx,
d9285e
	struct slbt_archive_meta_impl * mctx,
73a403
	int                             fdout)
d9285e
{
41a868
	int                             fdtmp;
41a868
	bool                            fsort;
41a868
	bool                            fcoff;
41a868
	const char *                    dot;
41a868
	const char *                    mark;
41a868
	const char *                    regex;
41a868
	const char **                   symv;
41a868
	const char **                   symstrv;
41a868
	regex_t                         regctx;
41a868
	regmatch_t                      pmatch[2] = {{0,0},{0,0}};
41a868
	char                            strbuf[4096];
41a868
41a868
	fsort = !(dctx->cctx->fmtflags & SLBT_OUTPUT_ARCHIVE_NOSORT);
41a868
	fcoff = (mctx->ofmtattr & AR_OBJECT_ATTR_COFF);
41a868
41a868
	if ((fdtmp = slbt_tmpfile()) < 0)
41a868
		return SLBT_SYSTEM_ERROR(dctx,0);
41a868
41a868
	if (fsort && !mctx->mapstrv)
41a868
		if (slbt_update_mapstrv(dctx,mctx) < 0)
41a868
			return SLBT_NESTED_ERROR(dctx);
41a868
41a868
	if (slbt_ar_update_syminfo_ex(mctx->actx,fdtmp) < 0)
41a868
		return SLBT_NESTED_ERROR(dctx);
41a868
41a868
	if ((regex = dctx->cctx->regex))
41a868
		if (regcomp(&regctx,regex,REG_EXTENDED|REG_NEWLINE))
41a868
			return SLBT_CUSTOM_ERROR(
41a868
				dctx,
41a868
				SLBT_ERR_FLOW_ERROR);
41a868
41a868
	symstrv = fsort ? mctx->mapstrv : mctx->symstrv;
41a868
41a868
	if (slbt_dprintf(fdout,"  - Symbols:\n") < 0)
41a868
		return SLBT_SYSTEM_ERROR(dctx,0);
41a868
41a868
	for (symv=symstrv; *symv; symv++) {
41a868
		if (!fcoff || slbt_is_strong_coff_symbol(*symv)) {
41a868
			if (!regex || !regexec(&regctx,*symv,1,pmatch,0)) {
41a868
				if (slbt_au_output_one_symbol_yaml(
41a868
						fdout,mctx,*symv) < 0)
41a868
					return SLBT_SYSTEM_ERROR(dctx,0);
41a868
			}
41a868
41a868
		/* coff weak symbols: expsym = .weak.alias.strong */
41a868
		} else if (fcoff && !strncmp(*symv,".weak.",6)) {
41a868
			mark = &(*symv)[6];
41a868
			dot  = strchr(mark,'.');
41a868
41a868
			strncpy(strbuf,mark,dot-mark);
41a868
			strbuf[dot-mark] = '\0';
41a868
41a868
			if (!regex || !regexec(&regctx,strbuf,1,pmatch,0))
41a868
				if (slbt_au_output_one_symbol_yaml(
41a868
						fdout,mctx,strbuf) < 0)
41a868
					return SLBT_SYSTEM_ERROR(dctx,0);
41a868
		}
41a868
	}
41a868
41a868
	if (regex)
41a868
		regfree(&regctx);
d9285e
d9285e
	return 0;
d9285e
}
d9285e
3fa3e3
int slbt_au_output_symbols(const struct slbt_archive_meta * meta)
d9285e
{
d9285e
	struct slbt_archive_meta_impl * mctx;
d9285e
	const struct slbt_driver_ctx *  dctx;
73a403
	int                             fdout;
d9285e
d9285e
	mctx = slbt_archive_meta_ictx(meta);
d9285e
	dctx = (slbt_archive_meta_ictx(meta))->dctx;
d9285e
73a403
	fdout = slbt_driver_fdout(dctx);
d9285e
d9285e
	if (!meta->a_memberv)
d9285e
		return 0;
d9285e
d9285e
	switch (dctx->cctx->fmtflags & SLBT_PRETTY_FLAGS) {
d9285e
		case SLBT_PRETTY_YAML:
3fa3e3
			return slbt_au_output_symbols_yaml(
73a403
				dctx,mctx,fdout);
d9285e
d9285e
		case SLBT_PRETTY_POSIX:
3fa3e3
			return slbt_au_output_symbols_posix(
73a403
				dctx,mctx,fdout);
d9285e
d9285e
		default:
3fa3e3
			return slbt_au_output_symbols_yaml(
73a403
				dctx,mctx,fdout);
d9285e
	}
d9285e
}