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 }