19950eceeSBaptiste Daroussin /*- 29950eceeSBaptiste Daroussin * Copyright (c) 2013 Baptiste Daroussin <bapt@FreeBSD.org> 39950eceeSBaptiste Daroussin * All rights reserved. 49950eceeSBaptiste Daroussin * 59950eceeSBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 69950eceeSBaptiste Daroussin * modification, are permitted provided that the following conditions 79950eceeSBaptiste Daroussin * are met: 89950eceeSBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright 99950eceeSBaptiste Daroussin * notice, this list of conditions and the following disclaimer. 109950eceeSBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright 119950eceeSBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 129950eceeSBaptiste Daroussin * documentation and/or other materials provided with the distribution. 139950eceeSBaptiste Daroussin * 149950eceeSBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 159950eceeSBaptiste Daroussin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 169950eceeSBaptiste Daroussin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 179950eceeSBaptiste Daroussin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 189950eceeSBaptiste Daroussin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 199950eceeSBaptiste Daroussin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 209950eceeSBaptiste Daroussin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 219950eceeSBaptiste Daroussin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 229950eceeSBaptiste Daroussin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 239950eceeSBaptiste Daroussin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 249950eceeSBaptiste Daroussin * SUCH DAMAGE. 259950eceeSBaptiste Daroussin */ 269950eceeSBaptiste Daroussin 279950eceeSBaptiste Daroussin #include <sys/cdefs.h> 289950eceeSBaptiste Daroussin __FBSDID("$FreeBSD$"); 299950eceeSBaptiste Daroussin 309950eceeSBaptiste Daroussin #include <sys/param.h> 319950eceeSBaptiste Daroussin #include <sys/sbuf.h> 329950eceeSBaptiste Daroussin #include <sys/elf_common.h> 339950eceeSBaptiste Daroussin #include <sys/endian.h> 349950eceeSBaptiste Daroussin 3540274a2dSBaptiste Daroussin #include <assert.h> 36e3ededfaSBryan Drewery #include <yaml.h> 379950eceeSBaptiste Daroussin #include <ctype.h> 389950eceeSBaptiste Daroussin #include <err.h> 399950eceeSBaptiste Daroussin #include <errno.h> 409950eceeSBaptiste Daroussin #include <fcntl.h> 419950eceeSBaptiste Daroussin #include <gelf.h> 429950eceeSBaptiste Daroussin #include <inttypes.h> 439950eceeSBaptiste Daroussin #include <paths.h> 449950eceeSBaptiste Daroussin #include <stdbool.h> 459950eceeSBaptiste Daroussin #include <string.h> 469950eceeSBaptiste Daroussin #include <unistd.h> 479950eceeSBaptiste Daroussin 489950eceeSBaptiste Daroussin #include "elf_tables.h" 499950eceeSBaptiste Daroussin #include "config.h" 509950eceeSBaptiste Daroussin 519950eceeSBaptiste Daroussin #define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */ 529950eceeSBaptiste Daroussin 539950eceeSBaptiste Daroussin struct config_entry { 549950eceeSBaptiste Daroussin uint8_t type; 559950eceeSBaptiste Daroussin const char *key; 569950eceeSBaptiste Daroussin const char *val; 579950eceeSBaptiste Daroussin char *value; 589950eceeSBaptiste Daroussin bool envset; 599950eceeSBaptiste Daroussin }; 609950eceeSBaptiste Daroussin 619950eceeSBaptiste Daroussin static struct config_entry c[] = { 629950eceeSBaptiste Daroussin [PACKAGESITE] = { 639950eceeSBaptiste Daroussin PKG_CONFIG_STRING, 649950eceeSBaptiste Daroussin "PACKAGESITE", 6562940ea9SBryan Drewery URL_SCHEME_PREFIX "http://pkg.FreeBSD.org/${ABI}/latest", 669950eceeSBaptiste Daroussin NULL, 679950eceeSBaptiste Daroussin false, 689950eceeSBaptiste Daroussin }, 699950eceeSBaptiste Daroussin [ABI] = { 709950eceeSBaptiste Daroussin PKG_CONFIG_STRING, 719950eceeSBaptiste Daroussin "ABI", 729950eceeSBaptiste Daroussin NULL, 739950eceeSBaptiste Daroussin NULL, 749950eceeSBaptiste Daroussin false, 759950eceeSBaptiste Daroussin }, 769950eceeSBaptiste Daroussin [MIRROR_TYPE] = { 779950eceeSBaptiste Daroussin PKG_CONFIG_STRING, 789950eceeSBaptiste Daroussin "MIRROR_TYPE", 799950eceeSBaptiste Daroussin "SRV", 809950eceeSBaptiste Daroussin NULL, 819950eceeSBaptiste Daroussin false, 829950eceeSBaptiste Daroussin }, 839950eceeSBaptiste Daroussin [ASSUME_ALWAYS_YES] = { 849950eceeSBaptiste Daroussin PKG_CONFIG_BOOL, 859950eceeSBaptiste Daroussin "ASSUME_ALWAYS_YES", 869950eceeSBaptiste Daroussin "NO", 879950eceeSBaptiste Daroussin NULL, 889950eceeSBaptiste Daroussin false, 899950eceeSBaptiste Daroussin } 909950eceeSBaptiste Daroussin }; 919950eceeSBaptiste Daroussin 929950eceeSBaptiste Daroussin static const char * 939950eceeSBaptiste Daroussin elf_corres_to_string(struct _elf_corres *m, int e) 949950eceeSBaptiste Daroussin { 959950eceeSBaptiste Daroussin int i; 969950eceeSBaptiste Daroussin 979950eceeSBaptiste Daroussin for (i = 0; m[i].string != NULL; i++) 989950eceeSBaptiste Daroussin if (m[i].elf_nb == e) 999950eceeSBaptiste Daroussin return (m[i].string); 1009950eceeSBaptiste Daroussin 1019950eceeSBaptiste Daroussin return ("unknown"); 1029950eceeSBaptiste Daroussin } 1039950eceeSBaptiste Daroussin 10440274a2dSBaptiste Daroussin static const char * 10540274a2dSBaptiste Daroussin aeabi_parse_arm_attributes(void *data, size_t length) 10640274a2dSBaptiste Daroussin { 10740274a2dSBaptiste Daroussin uint32_t sect_len; 10840274a2dSBaptiste Daroussin uint8_t *section = data; 10940274a2dSBaptiste Daroussin 11040274a2dSBaptiste Daroussin #define MOVE(len) do { \ 11140274a2dSBaptiste Daroussin assert(length >= (len)); \ 11240274a2dSBaptiste Daroussin section += (len); \ 11340274a2dSBaptiste Daroussin length -= (len); \ 11440274a2dSBaptiste Daroussin } while (0) 11540274a2dSBaptiste Daroussin 11640274a2dSBaptiste Daroussin if (length == 0 || *section != 'A') 11740274a2dSBaptiste Daroussin return (NULL); 11840274a2dSBaptiste Daroussin 11940274a2dSBaptiste Daroussin MOVE(1); 12040274a2dSBaptiste Daroussin 12140274a2dSBaptiste Daroussin /* Read the section length */ 12240274a2dSBaptiste Daroussin if (length < sizeof(sect_len)) 12340274a2dSBaptiste Daroussin return (NULL); 12440274a2dSBaptiste Daroussin 12540274a2dSBaptiste Daroussin memcpy(§_len, section, sizeof(sect_len)); 12640274a2dSBaptiste Daroussin 12740274a2dSBaptiste Daroussin /* 12840274a2dSBaptiste Daroussin * The section length should be no longer than the section it is within 12940274a2dSBaptiste Daroussin */ 13040274a2dSBaptiste Daroussin if (sect_len > length) 13140274a2dSBaptiste Daroussin return (NULL); 13240274a2dSBaptiste Daroussin 13340274a2dSBaptiste Daroussin MOVE(sizeof(sect_len)); 13440274a2dSBaptiste Daroussin 13540274a2dSBaptiste Daroussin /* Skip the vendor name */ 13640274a2dSBaptiste Daroussin while (length != 0) { 13740274a2dSBaptiste Daroussin if (*section == '\0') 13840274a2dSBaptiste Daroussin break; 13940274a2dSBaptiste Daroussin MOVE(1); 14040274a2dSBaptiste Daroussin } 14140274a2dSBaptiste Daroussin if (length == 0) 14240274a2dSBaptiste Daroussin return (NULL); 14340274a2dSBaptiste Daroussin MOVE(1); 14440274a2dSBaptiste Daroussin 14540274a2dSBaptiste Daroussin while (length != 0) { 14640274a2dSBaptiste Daroussin uint32_t tag_length; 14740274a2dSBaptiste Daroussin 14840274a2dSBaptiste Daroussin switch(*section) { 14940274a2dSBaptiste Daroussin case 1: /* Tag_File */ 15040274a2dSBaptiste Daroussin MOVE(1); 15140274a2dSBaptiste Daroussin if (length < sizeof(tag_length)) 15240274a2dSBaptiste Daroussin return (NULL); 15340274a2dSBaptiste Daroussin memcpy(&tag_length, section, sizeof(tag_length)); 15440274a2dSBaptiste Daroussin break; 15540274a2dSBaptiste Daroussin case 2: /* Tag_Section */ 15640274a2dSBaptiste Daroussin case 3: /* Tag_Symbol */ 15740274a2dSBaptiste Daroussin default: 15840274a2dSBaptiste Daroussin return (NULL); 15940274a2dSBaptiste Daroussin } 16040274a2dSBaptiste Daroussin /* At least space for the tag and size */ 16140274a2dSBaptiste Daroussin if (tag_length <= 5) 16240274a2dSBaptiste Daroussin return (NULL); 16340274a2dSBaptiste Daroussin tag_length--; 16440274a2dSBaptiste Daroussin /* Check the tag fits */ 16540274a2dSBaptiste Daroussin if (tag_length > length) 16640274a2dSBaptiste Daroussin return (NULL); 16740274a2dSBaptiste Daroussin 16840274a2dSBaptiste Daroussin #define MOVE_TAG(len) do { \ 16940274a2dSBaptiste Daroussin assert(tag_length >= (len)); \ 17040274a2dSBaptiste Daroussin MOVE(len); \ 17140274a2dSBaptiste Daroussin tag_length -= (len); \ 17240274a2dSBaptiste Daroussin } while(0) 17340274a2dSBaptiste Daroussin 17440274a2dSBaptiste Daroussin MOVE(sizeof(tag_length)); 17540274a2dSBaptiste Daroussin tag_length -= sizeof(tag_length); 17640274a2dSBaptiste Daroussin 17740274a2dSBaptiste Daroussin while (tag_length != 0) { 17840274a2dSBaptiste Daroussin uint8_t tag; 17940274a2dSBaptiste Daroussin 18040274a2dSBaptiste Daroussin assert(tag_length >= length); 18140274a2dSBaptiste Daroussin 18240274a2dSBaptiste Daroussin tag = *section; 18340274a2dSBaptiste Daroussin MOVE_TAG(1); 18440274a2dSBaptiste Daroussin 18540274a2dSBaptiste Daroussin /* 18640274a2dSBaptiste Daroussin * These tag values come from: 18740274a2dSBaptiste Daroussin * 18840274a2dSBaptiste Daroussin * Addenda to, and Errata in, the ABI for the 18940274a2dSBaptiste Daroussin * ARM Architecture. Release 2.08, section 2.3. 19040274a2dSBaptiste Daroussin */ 19140274a2dSBaptiste Daroussin if (tag == 6) { /* == Tag_CPU_arch */ 19240274a2dSBaptiste Daroussin uint8_t val; 19340274a2dSBaptiste Daroussin 19440274a2dSBaptiste Daroussin val = *section; 19540274a2dSBaptiste Daroussin /* 19640274a2dSBaptiste Daroussin * We don't support values that require 19740274a2dSBaptiste Daroussin * more than one byte. 19840274a2dSBaptiste Daroussin */ 19940274a2dSBaptiste Daroussin if (val & (1 << 7)) 20040274a2dSBaptiste Daroussin return (NULL); 20140274a2dSBaptiste Daroussin 20240274a2dSBaptiste Daroussin /* We have an ARMv4 or ARMv5 */ 20340274a2dSBaptiste Daroussin if (val <= 5) 20440274a2dSBaptiste Daroussin return ("arm"); 20540274a2dSBaptiste Daroussin else /* We have an ARMv6+ */ 20640274a2dSBaptiste Daroussin return ("armv6"); 20740274a2dSBaptiste Daroussin } else if (tag == 4 || tag == 5 || tag == 32 || 20840274a2dSBaptiste Daroussin tag == 65 || tag == 67) { 20940274a2dSBaptiste Daroussin while (*section != '\0' && length != 0) 21040274a2dSBaptiste Daroussin MOVE_TAG(1); 21140274a2dSBaptiste Daroussin if (tag_length == 0) 21240274a2dSBaptiste Daroussin return (NULL); 21340274a2dSBaptiste Daroussin /* Skip the last byte */ 21440274a2dSBaptiste Daroussin MOVE_TAG(1); 21540274a2dSBaptiste Daroussin } else if ((tag >= 7 && tag <= 31) || tag == 34 || 21640274a2dSBaptiste Daroussin tag == 36 || tag == 38 || tag == 42 || tag == 44 || 21740274a2dSBaptiste Daroussin tag == 64 || tag == 66 || tag == 68 || tag == 70) { 21840274a2dSBaptiste Daroussin /* Skip the uleb128 data */ 21940274a2dSBaptiste Daroussin while (*section & (1 << 7) && length != 0) 22040274a2dSBaptiste Daroussin MOVE_TAG(1); 22140274a2dSBaptiste Daroussin if (tag_length == 0) 22240274a2dSBaptiste Daroussin return (NULL); 22340274a2dSBaptiste Daroussin /* Skip the last byte */ 22440274a2dSBaptiste Daroussin MOVE_TAG(1); 22540274a2dSBaptiste Daroussin } else 22640274a2dSBaptiste Daroussin return (NULL); 22740274a2dSBaptiste Daroussin #undef MOVE_TAG 22840274a2dSBaptiste Daroussin } 22940274a2dSBaptiste Daroussin 23040274a2dSBaptiste Daroussin break; 23140274a2dSBaptiste Daroussin } 23240274a2dSBaptiste Daroussin return (NULL); 23340274a2dSBaptiste Daroussin #undef MOVE 23440274a2dSBaptiste Daroussin } 23540274a2dSBaptiste Daroussin 2369950eceeSBaptiste Daroussin static int 2379950eceeSBaptiste Daroussin pkg_get_myabi(char *dest, size_t sz) 2389950eceeSBaptiste Daroussin { 2399950eceeSBaptiste Daroussin Elf *elf; 2409950eceeSBaptiste Daroussin Elf_Data *data; 2419950eceeSBaptiste Daroussin Elf_Note note; 2429950eceeSBaptiste Daroussin Elf_Scn *scn; 2439950eceeSBaptiste Daroussin char *src, *osname; 24440274a2dSBaptiste Daroussin const char *arch, *abi, *fpu, *endian_corres_str; 24540274a2dSBaptiste Daroussin const char *wordsize_corres_str; 2469950eceeSBaptiste Daroussin GElf_Ehdr elfhdr; 2479950eceeSBaptiste Daroussin GElf_Shdr shdr; 2489950eceeSBaptiste Daroussin int fd, i, ret; 2499950eceeSBaptiste Daroussin uint32_t version; 2509950eceeSBaptiste Daroussin 2519950eceeSBaptiste Daroussin version = 0; 2529950eceeSBaptiste Daroussin ret = -1; 2539950eceeSBaptiste Daroussin scn = NULL; 2549950eceeSBaptiste Daroussin abi = NULL; 2559950eceeSBaptiste Daroussin 2569950eceeSBaptiste Daroussin if (elf_version(EV_CURRENT) == EV_NONE) { 2579950eceeSBaptiste Daroussin warnx("ELF library initialization failed: %s", 2589950eceeSBaptiste Daroussin elf_errmsg(-1)); 2599950eceeSBaptiste Daroussin return (-1); 2609950eceeSBaptiste Daroussin } 2619950eceeSBaptiste Daroussin 2629950eceeSBaptiste Daroussin if ((fd = open(_PATH_BSHELL, O_RDONLY)) < 0) { 2639950eceeSBaptiste Daroussin warn("open()"); 2649950eceeSBaptiste Daroussin return (-1); 2659950eceeSBaptiste Daroussin } 2669950eceeSBaptiste Daroussin 2679950eceeSBaptiste Daroussin if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 2689950eceeSBaptiste Daroussin ret = -1; 2699950eceeSBaptiste Daroussin warnx("elf_begin() failed: %s.", elf_errmsg(-1)); 2709950eceeSBaptiste Daroussin goto cleanup; 2719950eceeSBaptiste Daroussin } 2729950eceeSBaptiste Daroussin 2739950eceeSBaptiste Daroussin if (gelf_getehdr(elf, &elfhdr) == NULL) { 2749950eceeSBaptiste Daroussin ret = -1; 2759950eceeSBaptiste Daroussin warn("getehdr() failed: %s.", elf_errmsg(-1)); 2769950eceeSBaptiste Daroussin goto cleanup; 2779950eceeSBaptiste Daroussin } 2789950eceeSBaptiste Daroussin while ((scn = elf_nextscn(elf, scn)) != NULL) { 2799950eceeSBaptiste Daroussin if (gelf_getshdr(scn, &shdr) != &shdr) { 2809950eceeSBaptiste Daroussin ret = -1; 2819950eceeSBaptiste Daroussin warn("getshdr() failed: %s.", elf_errmsg(-1)); 2829950eceeSBaptiste Daroussin goto cleanup; 2839950eceeSBaptiste Daroussin } 2849950eceeSBaptiste Daroussin 2859950eceeSBaptiste Daroussin if (shdr.sh_type == SHT_NOTE) 2869950eceeSBaptiste Daroussin break; 2879950eceeSBaptiste Daroussin } 2889950eceeSBaptiste Daroussin 2899950eceeSBaptiste Daroussin if (scn == NULL) { 2909950eceeSBaptiste Daroussin ret = -1; 2919950eceeSBaptiste Daroussin warn("failed to get the note section"); 2929950eceeSBaptiste Daroussin goto cleanup; 2939950eceeSBaptiste Daroussin } 2949950eceeSBaptiste Daroussin 2959950eceeSBaptiste Daroussin data = elf_getdata(scn, NULL); 2969950eceeSBaptiste Daroussin src = data->d_buf; 2979950eceeSBaptiste Daroussin for (;;) { 2989950eceeSBaptiste Daroussin memcpy(¬e, src, sizeof(Elf_Note)); 2999950eceeSBaptiste Daroussin src += sizeof(Elf_Note); 3009950eceeSBaptiste Daroussin if (note.n_type == NT_VERSION) 3019950eceeSBaptiste Daroussin break; 3029950eceeSBaptiste Daroussin src += note.n_namesz + note.n_descsz; 3039950eceeSBaptiste Daroussin } 3049950eceeSBaptiste Daroussin osname = src; 3059950eceeSBaptiste Daroussin src += roundup2(note.n_namesz, 4); 3069950eceeSBaptiste Daroussin if (elfhdr.e_ident[EI_DATA] == ELFDATA2MSB) 3079950eceeSBaptiste Daroussin version = be32dec(src); 3089950eceeSBaptiste Daroussin else 3099950eceeSBaptiste Daroussin version = le32dec(src); 3109950eceeSBaptiste Daroussin 3119950eceeSBaptiste Daroussin for (i = 0; osname[i] != '\0'; i++) 3129950eceeSBaptiste Daroussin osname[i] = (char)tolower(osname[i]); 3139950eceeSBaptiste Daroussin 31440274a2dSBaptiste Daroussin wordsize_corres_str = elf_corres_to_string(wordsize_corres, 31540274a2dSBaptiste Daroussin (int)elfhdr.e_ident[EI_CLASS]); 31640274a2dSBaptiste Daroussin 31740274a2dSBaptiste Daroussin arch = elf_corres_to_string(mach_corres, (int) elfhdr.e_machine); 31840274a2dSBaptiste Daroussin 31940274a2dSBaptiste Daroussin snprintf(dest, sz, "%s:%d", 32040274a2dSBaptiste Daroussin osname, version / 100000); 3219950eceeSBaptiste Daroussin 3229950eceeSBaptiste Daroussin ret = 0; 3239950eceeSBaptiste Daroussin 3249950eceeSBaptiste Daroussin switch (elfhdr.e_machine) { 3259950eceeSBaptiste Daroussin case EM_ARM: 32640274a2dSBaptiste Daroussin endian_corres_str = elf_corres_to_string(endian_corres, 32740274a2dSBaptiste Daroussin (int)elfhdr.e_ident[EI_DATA]); 32840274a2dSBaptiste Daroussin 3294b5ef056SBaptiste Daroussin /* FreeBSD doesn't support the hard-float ABI yet */ 3304b5ef056SBaptiste Daroussin fpu = "softfp"; 3314b5ef056SBaptiste Daroussin if ((elfhdr.e_flags & 0xFF000000) != 0) { 33240274a2dSBaptiste Daroussin const char *sh_name = NULL; 33340274a2dSBaptiste Daroussin size_t shstrndx; 33440274a2dSBaptiste Daroussin 3354b5ef056SBaptiste Daroussin /* This is an EABI file, the conformance level is set */ 3364b5ef056SBaptiste Daroussin abi = "eabi"; 33740274a2dSBaptiste Daroussin /* Find which TARGET_ARCH we are building for. */ 33840274a2dSBaptiste Daroussin elf_getshdrstrndx(elf, &shstrndx); 33940274a2dSBaptiste Daroussin while ((scn = elf_nextscn(elf, scn)) != NULL) { 34040274a2dSBaptiste Daroussin sh_name = NULL; 34140274a2dSBaptiste Daroussin if (gelf_getshdr(scn, &shdr) != &shdr) { 34240274a2dSBaptiste Daroussin scn = NULL; 34340274a2dSBaptiste Daroussin break; 34440274a2dSBaptiste Daroussin } 34540274a2dSBaptiste Daroussin 34640274a2dSBaptiste Daroussin sh_name = elf_strptr(elf, shstrndx, 34740274a2dSBaptiste Daroussin shdr.sh_name); 34840274a2dSBaptiste Daroussin if (sh_name == NULL) 34940274a2dSBaptiste Daroussin continue; 35040274a2dSBaptiste Daroussin if (strcmp(".ARM.attributes", sh_name) == 0) 35140274a2dSBaptiste Daroussin break; 35240274a2dSBaptiste Daroussin } 35340274a2dSBaptiste Daroussin if (scn != NULL && sh_name != NULL) { 35440274a2dSBaptiste Daroussin data = elf_getdata(scn, NULL); 35540274a2dSBaptiste Daroussin /* 35640274a2dSBaptiste Daroussin * Prior to FreeBSD 10.0 libelf would return 35740274a2dSBaptiste Daroussin * NULL from elf_getdata on the .ARM.attributes 35840274a2dSBaptiste Daroussin * section. As this was the first release to 35940274a2dSBaptiste Daroussin * get armv6 support assume a NULL value means 36040274a2dSBaptiste Daroussin * arm. 36140274a2dSBaptiste Daroussin * 36240274a2dSBaptiste Daroussin * This assumption can be removed when 9.x 36340274a2dSBaptiste Daroussin * is unsupported. 36440274a2dSBaptiste Daroussin */ 36540274a2dSBaptiste Daroussin if (data != NULL) { 36640274a2dSBaptiste Daroussin arch = aeabi_parse_arm_attributes( 36740274a2dSBaptiste Daroussin data->d_buf, data->d_size); 36840274a2dSBaptiste Daroussin if (arch == NULL) { 36940274a2dSBaptiste Daroussin ret = 1; 37040274a2dSBaptiste Daroussin warn("unknown ARM ARCH"); 37140274a2dSBaptiste Daroussin goto cleanup; 37240274a2dSBaptiste Daroussin } 37340274a2dSBaptiste Daroussin } 37440274a2dSBaptiste Daroussin } else { 37540274a2dSBaptiste Daroussin ret = 1; 37640274a2dSBaptiste Daroussin warn("Unable to find the .ARM.attributes " 37740274a2dSBaptiste Daroussin "section"); 37840274a2dSBaptiste Daroussin goto cleanup; 37940274a2dSBaptiste Daroussin } 3804b5ef056SBaptiste Daroussin } else if (elfhdr.e_ident[EI_OSABI] != ELFOSABI_NONE) { 3814b5ef056SBaptiste Daroussin /* 3824b5ef056SBaptiste Daroussin * EABI executables all have this field set to 3834b5ef056SBaptiste Daroussin * ELFOSABI_NONE, therefore it must be an oabi file. 3844b5ef056SBaptiste Daroussin */ 3854b5ef056SBaptiste Daroussin abi = "oabi"; 3864b5ef056SBaptiste Daroussin } else { 3874b5ef056SBaptiste Daroussin ret = 1; 38840274a2dSBaptiste Daroussin warn("unknown ARM ABI"); 3894b5ef056SBaptiste Daroussin goto cleanup; 3904b5ef056SBaptiste Daroussin } 3919950eceeSBaptiste Daroussin snprintf(dest + strlen(dest), sz - strlen(dest), 39240274a2dSBaptiste Daroussin ":%s:%s:%s:%s:%s", arch, wordsize_corres_str, 39340274a2dSBaptiste Daroussin endian_corres_str, abi, fpu); 3949950eceeSBaptiste Daroussin break; 3959950eceeSBaptiste Daroussin case EM_MIPS: 3969950eceeSBaptiste Daroussin /* 3979950eceeSBaptiste Daroussin * this is taken from binutils sources: 3989950eceeSBaptiste Daroussin * include/elf/mips.h 3999950eceeSBaptiste Daroussin * mapping is figured out from binutils: 4009950eceeSBaptiste Daroussin * gas/config/tc-mips.c 4019950eceeSBaptiste Daroussin */ 4029950eceeSBaptiste Daroussin switch (elfhdr.e_flags & EF_MIPS_ABI) { 4039950eceeSBaptiste Daroussin case E_MIPS_ABI_O32: 4049950eceeSBaptiste Daroussin abi = "o32"; 4059950eceeSBaptiste Daroussin break; 4069950eceeSBaptiste Daroussin case E_MIPS_ABI_N32: 4079950eceeSBaptiste Daroussin abi = "n32"; 4089950eceeSBaptiste Daroussin break; 4099950eceeSBaptiste Daroussin default: 4109950eceeSBaptiste Daroussin if (elfhdr.e_ident[EI_DATA] == 4119950eceeSBaptiste Daroussin ELFCLASS32) 4129950eceeSBaptiste Daroussin abi = "o32"; 4139950eceeSBaptiste Daroussin else if (elfhdr.e_ident[EI_DATA] == 4149950eceeSBaptiste Daroussin ELFCLASS64) 4159950eceeSBaptiste Daroussin abi = "n64"; 4169950eceeSBaptiste Daroussin break; 4179950eceeSBaptiste Daroussin } 41840274a2dSBaptiste Daroussin endian_corres_str = elf_corres_to_string(endian_corres, 41940274a2dSBaptiste Daroussin (int)elfhdr.e_ident[EI_DATA]); 42040274a2dSBaptiste Daroussin 42140274a2dSBaptiste Daroussin snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s:%s:%s", 42240274a2dSBaptiste Daroussin arch, wordsize_corres_str, endian_corres_str, abi); 4239950eceeSBaptiste Daroussin break; 42440274a2dSBaptiste Daroussin default: 42540274a2dSBaptiste Daroussin snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s", 42640274a2dSBaptiste Daroussin arch, wordsize_corres_str); 4279950eceeSBaptiste Daroussin } 4289950eceeSBaptiste Daroussin 4299950eceeSBaptiste Daroussin cleanup: 4309950eceeSBaptiste Daroussin if (elf != NULL) 4319950eceeSBaptiste Daroussin elf_end(elf); 4329950eceeSBaptiste Daroussin 4339950eceeSBaptiste Daroussin close(fd); 4349950eceeSBaptiste Daroussin return (ret); 4359950eceeSBaptiste Daroussin } 4369950eceeSBaptiste Daroussin 4379950eceeSBaptiste Daroussin static void 4389950eceeSBaptiste Daroussin subst_packagesite(const char *abi) 4399950eceeSBaptiste Daroussin { 4409950eceeSBaptiste Daroussin struct sbuf *newval; 4419950eceeSBaptiste Daroussin const char *variable_string; 4429950eceeSBaptiste Daroussin const char *oldval; 4439950eceeSBaptiste Daroussin 4449950eceeSBaptiste Daroussin if (c[PACKAGESITE].value != NULL) 4459950eceeSBaptiste Daroussin oldval = c[PACKAGESITE].value; 4469950eceeSBaptiste Daroussin else 4479950eceeSBaptiste Daroussin oldval = c[PACKAGESITE].val; 4489950eceeSBaptiste Daroussin 4499950eceeSBaptiste Daroussin if ((variable_string = strstr(oldval, "${ABI}")) == NULL) 4509950eceeSBaptiste Daroussin return; 4519950eceeSBaptiste Daroussin 4529950eceeSBaptiste Daroussin newval = sbuf_new_auto(); 4539950eceeSBaptiste Daroussin sbuf_bcat(newval, oldval, variable_string - oldval); 4549950eceeSBaptiste Daroussin sbuf_cat(newval, abi); 4559950eceeSBaptiste Daroussin sbuf_cat(newval, variable_string + strlen("${ABI}")); 4569950eceeSBaptiste Daroussin sbuf_finish(newval); 4579950eceeSBaptiste Daroussin 4589950eceeSBaptiste Daroussin free(c[PACKAGESITE].value); 4599950eceeSBaptiste Daroussin c[PACKAGESITE].value = strdup(sbuf_data(newval)); 4609950eceeSBaptiste Daroussin } 4619950eceeSBaptiste Daroussin 4629950eceeSBaptiste Daroussin static void 4639950eceeSBaptiste Daroussin config_parse(yaml_document_t *doc, yaml_node_t *node) 4649950eceeSBaptiste Daroussin { 4659950eceeSBaptiste Daroussin yaml_node_pair_t *pair; 4669950eceeSBaptiste Daroussin yaml_node_t *key, *val; 4679950eceeSBaptiste Daroussin struct sbuf *buf = sbuf_new_auto(); 4689950eceeSBaptiste Daroussin int i; 4699950eceeSBaptiste Daroussin size_t j; 4709950eceeSBaptiste Daroussin 4719950eceeSBaptiste Daroussin pair = node->data.mapping.pairs.start; 4729950eceeSBaptiste Daroussin 4739950eceeSBaptiste Daroussin while (pair < node->data.mapping.pairs.top) { 4749950eceeSBaptiste Daroussin key = yaml_document_get_node(doc, pair->key); 4759950eceeSBaptiste Daroussin val = yaml_document_get_node(doc, pair->value); 4769950eceeSBaptiste Daroussin 4779950eceeSBaptiste Daroussin /* 4789950eceeSBaptiste Daroussin * ignoring silently empty keys can be empty lines 4799950eceeSBaptiste Daroussin * or user mistakes 4809950eceeSBaptiste Daroussin */ 4819950eceeSBaptiste Daroussin if (key->data.scalar.length <= 0) { 4829950eceeSBaptiste Daroussin ++pair; 4839950eceeSBaptiste Daroussin continue; 4849950eceeSBaptiste Daroussin } 4859950eceeSBaptiste Daroussin 4869950eceeSBaptiste Daroussin /* 4879950eceeSBaptiste Daroussin * silently skip on purpose to allow user to leave 4889950eceeSBaptiste Daroussin * empty lines without complaining 4899950eceeSBaptiste Daroussin */ 4909950eceeSBaptiste Daroussin if (val->type == YAML_NO_NODE || 4919950eceeSBaptiste Daroussin (val->type == YAML_SCALAR_NODE && 4929950eceeSBaptiste Daroussin val->data.scalar.length <= 0)) { 4939950eceeSBaptiste Daroussin ++pair; 4949950eceeSBaptiste Daroussin continue; 4959950eceeSBaptiste Daroussin } 4969950eceeSBaptiste Daroussin 4979950eceeSBaptiste Daroussin sbuf_clear(buf); 4989950eceeSBaptiste Daroussin for (j = 0; j < strlen(key->data.scalar.value); ++j) 4999950eceeSBaptiste Daroussin sbuf_putc(buf, toupper(key->data.scalar.value[j])); 5009950eceeSBaptiste Daroussin 5019950eceeSBaptiste Daroussin sbuf_finish(buf); 5029950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) { 5039950eceeSBaptiste Daroussin if (strcmp(sbuf_data(buf), c[i].key) == 0) 5049950eceeSBaptiste Daroussin break; 5059950eceeSBaptiste Daroussin } 5069950eceeSBaptiste Daroussin 5079950eceeSBaptiste Daroussin if (i == CONFIG_SIZE) { 5089950eceeSBaptiste Daroussin ++pair; 5099950eceeSBaptiste Daroussin continue; 5109950eceeSBaptiste Daroussin } 5119950eceeSBaptiste Daroussin 5129950eceeSBaptiste Daroussin /* env has priority over config file */ 5139950eceeSBaptiste Daroussin if (c[i].envset) { 5149950eceeSBaptiste Daroussin ++pair; 5159950eceeSBaptiste Daroussin continue; 5169950eceeSBaptiste Daroussin } 5179950eceeSBaptiste Daroussin 5189950eceeSBaptiste Daroussin c[i].value = strdup(val->data.scalar.value); 5199950eceeSBaptiste Daroussin ++pair; 5209950eceeSBaptiste Daroussin } 5219950eceeSBaptiste Daroussin 5229950eceeSBaptiste Daroussin sbuf_delete(buf); 5239950eceeSBaptiste Daroussin } 5249950eceeSBaptiste Daroussin 5259950eceeSBaptiste Daroussin int 5269950eceeSBaptiste Daroussin config_init(void) 5279950eceeSBaptiste Daroussin { 5289950eceeSBaptiste Daroussin FILE *fp; 5299950eceeSBaptiste Daroussin yaml_parser_t parser; 5309950eceeSBaptiste Daroussin yaml_document_t doc; 5319950eceeSBaptiste Daroussin yaml_node_t *node; 5329950eceeSBaptiste Daroussin const char *val; 5339950eceeSBaptiste Daroussin int i; 5349950eceeSBaptiste Daroussin const char *localbase; 5359950eceeSBaptiste Daroussin char confpath[MAXPATHLEN]; 5369950eceeSBaptiste Daroussin char abi[BUFSIZ]; 5379950eceeSBaptiste Daroussin 5389950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) { 5399950eceeSBaptiste Daroussin val = getenv(c[i].key); 5409950eceeSBaptiste Daroussin if (val != NULL) { 5419950eceeSBaptiste Daroussin c[i].val = val; 5429950eceeSBaptiste Daroussin c[i].envset = true; 5439950eceeSBaptiste Daroussin } 5449950eceeSBaptiste Daroussin } 5459950eceeSBaptiste Daroussin 5469950eceeSBaptiste Daroussin localbase = getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE; 5479950eceeSBaptiste Daroussin snprintf(confpath, sizeof(confpath), "%s/etc/pkg.conf", localbase); 5489950eceeSBaptiste Daroussin 5499950eceeSBaptiste Daroussin if ((fp = fopen(confpath, "r")) == NULL) { 5509950eceeSBaptiste Daroussin if (errno != ENOENT) 551*4ff9a7efSBryan Drewery err(EXIT_FAILURE, "Unable to open configuration " 552*4ff9a7efSBryan Drewery "file %s", confpath); 5539950eceeSBaptiste Daroussin /* no configuration present */ 5549950eceeSBaptiste Daroussin goto finalize; 5559950eceeSBaptiste Daroussin } 5569950eceeSBaptiste Daroussin 5579950eceeSBaptiste Daroussin yaml_parser_initialize(&parser); 5589950eceeSBaptiste Daroussin yaml_parser_set_input_file(&parser, fp); 5599950eceeSBaptiste Daroussin yaml_parser_load(&parser, &doc); 5609950eceeSBaptiste Daroussin 5619950eceeSBaptiste Daroussin node = yaml_document_get_root_node(&doc); 5629950eceeSBaptiste Daroussin 5639950eceeSBaptiste Daroussin if (node != NULL) { 5649950eceeSBaptiste Daroussin if (node->type != YAML_MAPPING_NODE) 565*4ff9a7efSBryan Drewery warnx("Invalid configuration format, ignoring the " 566*4ff9a7efSBryan Drewery "configuration file"); 5679950eceeSBaptiste Daroussin else 5689950eceeSBaptiste Daroussin config_parse(&doc, node); 5699950eceeSBaptiste Daroussin } else { 570*4ff9a7efSBryan Drewery warnx("Invalid configuration format, ignoring the " 571*4ff9a7efSBryan Drewery "configuration file"); 5729950eceeSBaptiste Daroussin } 5739950eceeSBaptiste Daroussin 5749950eceeSBaptiste Daroussin yaml_document_delete(&doc); 5759950eceeSBaptiste Daroussin yaml_parser_delete(&parser); 5769950eceeSBaptiste Daroussin 5779950eceeSBaptiste Daroussin finalize: 5789950eceeSBaptiste Daroussin if (c[ABI].val == NULL && c[ABI].value == NULL) { 5799950eceeSBaptiste Daroussin if (pkg_get_myabi(abi, BUFSIZ) != 0) 580*4ff9a7efSBryan Drewery errx(EXIT_FAILURE, "Failed to determine the system " 581*4ff9a7efSBryan Drewery "ABI"); 5829950eceeSBaptiste Daroussin c[ABI].val = abi; 5839950eceeSBaptiste Daroussin } 5849950eceeSBaptiste Daroussin 585d5bf8a8bSBaptiste Daroussin subst_packagesite(c[ABI].value != NULL ? c[ABI].value : c[ABI].val); 5869950eceeSBaptiste Daroussin 5879950eceeSBaptiste Daroussin return (0); 5889950eceeSBaptiste Daroussin } 5899950eceeSBaptiste Daroussin 5909950eceeSBaptiste Daroussin int 5919950eceeSBaptiste Daroussin config_string(pkg_config_key k, const char **val) 5929950eceeSBaptiste Daroussin { 5939950eceeSBaptiste Daroussin if (c[k].type != PKG_CONFIG_STRING) 5949950eceeSBaptiste Daroussin return (-1); 5959950eceeSBaptiste Daroussin 5969950eceeSBaptiste Daroussin if (c[k].value != NULL) 5979950eceeSBaptiste Daroussin *val = c[k].value; 5989950eceeSBaptiste Daroussin else 5999950eceeSBaptiste Daroussin *val = c[k].val; 6009950eceeSBaptiste Daroussin 6019950eceeSBaptiste Daroussin return (0); 6029950eceeSBaptiste Daroussin } 6039950eceeSBaptiste Daroussin 6049950eceeSBaptiste Daroussin int 6059950eceeSBaptiste Daroussin config_bool(pkg_config_key k, bool *val) 6069950eceeSBaptiste Daroussin { 6079950eceeSBaptiste Daroussin const char *value; 6089950eceeSBaptiste Daroussin 6099950eceeSBaptiste Daroussin if (c[k].type != PKG_CONFIG_BOOL) 6109950eceeSBaptiste Daroussin return (-1); 6119950eceeSBaptiste Daroussin 6129950eceeSBaptiste Daroussin *val = false; 6139950eceeSBaptiste Daroussin 6149950eceeSBaptiste Daroussin if (c[k].value != NULL) 6159950eceeSBaptiste Daroussin value = c[k].value; 6169950eceeSBaptiste Daroussin else 6179950eceeSBaptiste Daroussin value = c[k].val; 6189950eceeSBaptiste Daroussin 6199950eceeSBaptiste Daroussin if (strcasecmp(value, "true") == 0 || 6209950eceeSBaptiste Daroussin strcasecmp(value, "yes") == 0 || 6219950eceeSBaptiste Daroussin strcasecmp(value, "on") == 0 || 6229950eceeSBaptiste Daroussin *value == '1') 6239950eceeSBaptiste Daroussin *val = true; 6249950eceeSBaptiste Daroussin 6259950eceeSBaptiste Daroussin return (0); 6269950eceeSBaptiste Daroussin } 6279950eceeSBaptiste Daroussin 6289950eceeSBaptiste Daroussin void 6299950eceeSBaptiste Daroussin config_finish(void) { 6309950eceeSBaptiste Daroussin int i; 6319950eceeSBaptiste Daroussin 6329950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) 6339950eceeSBaptiste Daroussin free(c[i].value); 6349950eceeSBaptiste Daroussin } 635