/ tests / lib / pkg_elf.c
pkg_elf.c
  1  /*-
  2   * Copyright(c) 2024 Baptiste Daroussin <bapt@FreeBSD.org>
  3   *
  4   * SPDX-License-Identifier: BSD-2-Clause
  5   */
  6  
  7  #include <sys/types.h>
  8  
  9  #include <string.h>
 10  
 11  #include <atf-c.h>
 12  #include <private/pkg.h>
 13  #include <private/pkg_abi.h>
 14  #include <private/binfmt.h>
 15  #include <xstring.h>
 16  #include <pkg.h>
 17  
 18  #ifndef __unused
 19  # ifdef __GNUC__
 20  # define __unused __attribute__ ((__unused__))
 21  # else
 22  # define __unused
 23  # endif
 24  #endif
 25  
 26  xstring *msg;
 27  
 28  ATF_TC_WITHOUT_HEAD(analyse_elf);
 29  
 30  int
 31  event_callback(void *data __unused, struct pkg_event *ev)
 32  {
 33  	switch (ev->type) {
 34  	case PKG_EVENT_ERROR:
 35  		xstring_reset(msg);
 36  		fprintf(msg->fp, "%s", ev->e_pkg_error.msg);
 37  		break;
 38  	default:
 39  		/* IGNORE */
 40  		break;
 41  	}
 42  
 43  	return (0);
 44  }
 45  
 46  ATF_TC_BODY(analyse_elf, tc)
 47  {
 48  	struct pkg *p = NULL;
 49  	char *binpath = NULL;
 50  	char *provided = NULL;
 51  	enum pkg_shlib_flags provided_flags = PKG_SHLIB_FLAGS_NONE;
 52  
 53  	ctx.abi.os = PKG_OS_FREEBSD;
 54  	ctx.abi.arch = PKG_ARCH_AMD64;
 55  
 56  	xasprintf(&binpath, "%s/frontend/libtestfbsd.so.1", atf_tc_get_config_var(tc, "srcdir"));
 57  
 58  	ATF_REQUIRE_EQ(EPKG_OK, pkg_new(&p, PKG_INSTALLED));
 59  	ATF_REQUIRE(p != NULL);
 60  
 61  	ATF_REQUIRE_EQ(vec_len(&p->shlibs_required), 0);
 62  	ATF_REQUIRE_EQ(pkg_analyse_elf(false, p, binpath, &provided, &provided_flags), EPKG_OK);
 63  	ATF_REQUIRE_EQ(vec_len(&p->shlibs_provided), 0);
 64  	ATF_REQUIRE_STREQ(provided, "libtestfbsd.so.1");
 65  	ATF_REQUIRE_EQ(provided_flags, PKG_SHLIB_FLAGS_NONE);
 66  	ATF_REQUIRE_EQ(vec_len(&p->shlibs_required), 1);
 67  	ATF_REQUIRE_STREQ(vec_first(&p->shlibs_required), "libc.so.7");
 68  	free(provided);
 69  	free(binpath);
 70  
 71  	provided = NULL;
 72  	provided_flags = PKG_SHLIB_FLAGS_NONE;
 73  	xasprintf(&binpath, "%s/Makefile", atf_tc_get_config_var(tc, "srcdir"));
 74  	ATF_REQUIRE_EQ(pkg_analyse_elf(false, p, binpath, &provided, &provided_flags), EPKG_END);
 75  	ATF_REQUIRE_EQ(vec_len(&p->shlibs_provided), 0);
 76  	ATF_REQUIRE_EQ(provided, NULL);
 77  	ATF_REQUIRE_EQ(provided_flags, PKG_SHLIB_FLAGS_NONE);
 78  	ATF_REQUIRE_EQ(vec_len(&p->shlibs_required), 1);
 79  	free(provided);
 80  	free(binpath);
 81  
 82  	provided = NULL;
 83  	provided_flags = PKG_SHLIB_FLAGS_NONE;
 84  	xasprintf(&binpath, "%s/frontend/libtest2fbsd.so.1", atf_tc_get_config_var(tc, "srcdir"));
 85  	ATF_REQUIRE_EQ(pkg_analyse_elf(false, p, binpath, &provided, &provided_flags), EPKG_OK);
 86  	ATF_REQUIRE_EQ(vec_len(&p->shlibs_provided), 0);
 87  	ATF_REQUIRE_STREQ(provided, "libtest2fbsd.so.1");
 88  	ATF_REQUIRE_EQ(provided_flags, PKG_SHLIB_FLAGS_NONE);
 89  	ATF_REQUIRE_EQ(vec_len(&p->shlibs_required), 2);
 90  	ATF_REQUIRE_STREQ(vec_first(&p->shlibs_required), "libc.so.7");
 91  	ATF_REQUIRE_STREQ(vec_last(&p->shlibs_required), "libfoo.so.1");
 92  	free(provided);
 93  	free(binpath);
 94  
 95  	pkg_free(p);
 96  }
 97  
 98  ATF_TC_WITHOUT_HEAD(static_lib_non_elf);
 99  
100  ATF_TC_BODY(static_lib_non_elf, tc)
101  {
102  	struct pkg *p = NULL;
103  	char *provided = NULL;
104  	enum pkg_shlib_flags provided_flags = PKG_SHLIB_FLAGS_NONE;
105  
106  	ctx.abi.os = PKG_OS_FREEBSD;
107  	ctx.abi.arch = PKG_ARCH_AMD64;
108  	ctx.developer_mode = true;
109  
110  	/* Create a non-ELF .a archive (e.g. WASM static library) */
111  	FILE *fp = fopen("dummy.txt", "w");
112  	ATF_REQUIRE(fp != NULL);
113  	fprintf(fp, "not an ELF object\n");
114  	fclose(fp);
115  	ATF_REQUIRE_EQ(0, system("ar rcs libwasm.a dummy.txt"));
116  
117  	/* Non-ELF .a should NOT set PKG_CONTAINS_STATIC_LIBS */
118  	ATF_REQUIRE_EQ(EPKG_OK, pkg_new(&p, PKG_INSTALLED));
119  	p->flags &= ~PKG_CONTAINS_STATIC_LIBS;
120  	ATF_REQUIRE_EQ(pkg_analyse_elf(true, p, "libwasm.a",
121  	    &provided, &provided_flags), EPKG_END);
122  	ATF_CHECK_EQ_MSG(0, p->flags & PKG_CONTAINS_STATIC_LIBS,
123  	    "non-ELF .a should not set PKG_CONTAINS_STATIC_LIBS");
124  	pkg_free(p);
125  	free(provided);
126  
127  #ifdef __ELF__
128  	/* ELF .a should set PKG_CONTAINS_STATIC_LIBS
129  	 * (only testable on ELF platforms where cc produces ELF objects) */
130  	fp = fopen("empty.c", "w");
131  	ATF_REQUIRE(fp != NULL);
132  	fprintf(fp, "void placeholder(void) {}\n");
133  	fclose(fp);
134  	ATF_REQUIRE_EQ(0, system("cc -c -o empty.o empty.c"));
135  	ATF_REQUIRE_EQ(0, system("ar rcs libnative.a empty.o"));
136  
137  	provided = NULL;
138  	provided_flags = PKG_SHLIB_FLAGS_NONE;
139  	ATF_REQUIRE_EQ(EPKG_OK, pkg_new(&p, PKG_INSTALLED));
140  	p->flags &= ~PKG_CONTAINS_STATIC_LIBS;
141  	ATF_REQUIRE_EQ(pkg_analyse_elf(true, p, "libnative.a",
142  	    &provided, &provided_flags), EPKG_END);
143  	ATF_CHECK_EQ_MSG(PKG_CONTAINS_STATIC_LIBS,
144  	    p->flags & PKG_CONTAINS_STATIC_LIBS,
145  	    "ELF .a should set PKG_CONTAINS_STATIC_LIBS");
146  	pkg_free(p);
147  	free(provided);
148  #endif
149  }
150  
151  ATF_TP_ADD_TCS(tp)
152  {
153  	ATF_TP_ADD_TC(tp, analyse_elf);
154  	ATF_TP_ADD_TC(tp, static_lib_non_elf);
155  
156  	return (atf_no_error());
157  }