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 35*40274a2dSBaptiste Daroussin #include <assert.h> 369950eceeSBaptiste Daroussin #include <bsdyml.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", 659950eceeSBaptiste Daroussin "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 104*40274a2dSBaptiste Daroussin static const char * 105*40274a2dSBaptiste Daroussin aeabi_parse_arm_attributes(void *data, size_t length) 106*40274a2dSBaptiste Daroussin { 107*40274a2dSBaptiste Daroussin uint32_t sect_len; 108*40274a2dSBaptiste Daroussin uint8_t *section = data; 109*40274a2dSBaptiste Daroussin 110*40274a2dSBaptiste Daroussin #define MOVE(len) do { \ 111*40274a2dSBaptiste Daroussin assert(length >= (len)); \ 112*40274a2dSBaptiste Daroussin section += (len); \ 113*40274a2dSBaptiste Daroussin length -= (len); \ 114*40274a2dSBaptiste Daroussin } while (0) 115*40274a2dSBaptiste Daroussin 116*40274a2dSBaptiste Daroussin if (length == 0 || *section != 'A') 117*40274a2dSBaptiste Daroussin return (NULL); 118*40274a2dSBaptiste Daroussin 119*40274a2dSBaptiste Daroussin MOVE(1); 120*40274a2dSBaptiste Daroussin 121*40274a2dSBaptiste Daroussin /* Read the section length */ 122*40274a2dSBaptiste Daroussin if (length < sizeof(sect_len)) 123*40274a2dSBaptiste Daroussin return (NULL); 124*40274a2dSBaptiste Daroussin 125*40274a2dSBaptiste Daroussin memcpy(§_len, section, sizeof(sect_len)); 126*40274a2dSBaptiste Daroussin 127*40274a2dSBaptiste Daroussin /* 128*40274a2dSBaptiste Daroussin * The section length should be no longer than the section it is within 129*40274a2dSBaptiste Daroussin */ 130*40274a2dSBaptiste Daroussin if (sect_len > length) 131*40274a2dSBaptiste Daroussin return (NULL); 132*40274a2dSBaptiste Daroussin 133*40274a2dSBaptiste Daroussin MOVE(sizeof(sect_len)); 134*40274a2dSBaptiste Daroussin 135*40274a2dSBaptiste Daroussin /* Skip the vendor name */ 136*40274a2dSBaptiste Daroussin while (length != 0) { 137*40274a2dSBaptiste Daroussin if (*section == '\0') 138*40274a2dSBaptiste Daroussin break; 139*40274a2dSBaptiste Daroussin MOVE(1); 140*40274a2dSBaptiste Daroussin } 141*40274a2dSBaptiste Daroussin if (length == 0) 142*40274a2dSBaptiste Daroussin return (NULL); 143*40274a2dSBaptiste Daroussin MOVE(1); 144*40274a2dSBaptiste Daroussin 145*40274a2dSBaptiste Daroussin while (length != 0) { 146*40274a2dSBaptiste Daroussin uint32_t tag_length; 147*40274a2dSBaptiste Daroussin 148*40274a2dSBaptiste Daroussin switch(*section) { 149*40274a2dSBaptiste Daroussin case 1: /* Tag_File */ 150*40274a2dSBaptiste Daroussin MOVE(1); 151*40274a2dSBaptiste Daroussin if (length < sizeof(tag_length)) 152*40274a2dSBaptiste Daroussin return (NULL); 153*40274a2dSBaptiste Daroussin memcpy(&tag_length, section, sizeof(tag_length)); 154*40274a2dSBaptiste Daroussin break; 155*40274a2dSBaptiste Daroussin case 2: /* Tag_Section */ 156*40274a2dSBaptiste Daroussin case 3: /* Tag_Symbol */ 157*40274a2dSBaptiste Daroussin default: 158*40274a2dSBaptiste Daroussin return (NULL); 159*40274a2dSBaptiste Daroussin } 160*40274a2dSBaptiste Daroussin /* At least space for the tag and size */ 161*40274a2dSBaptiste Daroussin if (tag_length <= 5) 162*40274a2dSBaptiste Daroussin return (NULL); 163*40274a2dSBaptiste Daroussin tag_length--; 164*40274a2dSBaptiste Daroussin /* Check the tag fits */ 165*40274a2dSBaptiste Daroussin if (tag_length > length) 166*40274a2dSBaptiste Daroussin return (NULL); 167*40274a2dSBaptiste Daroussin 168*40274a2dSBaptiste Daroussin #define MOVE_TAG(len) do { \ 169*40274a2dSBaptiste Daroussin assert(tag_length >= (len)); \ 170*40274a2dSBaptiste Daroussin MOVE(len); \ 171*40274a2dSBaptiste Daroussin tag_length -= (len); \ 172*40274a2dSBaptiste Daroussin } while(0) 173*40274a2dSBaptiste Daroussin 174*40274a2dSBaptiste Daroussin MOVE(sizeof(tag_length)); 175*40274a2dSBaptiste Daroussin tag_length -= sizeof(tag_length); 176*40274a2dSBaptiste Daroussin 177*40274a2dSBaptiste Daroussin while (tag_length != 0) { 178*40274a2dSBaptiste Daroussin uint8_t tag; 179*40274a2dSBaptiste Daroussin 180*40274a2dSBaptiste Daroussin assert(tag_length >= length); 181*40274a2dSBaptiste Daroussin 182*40274a2dSBaptiste Daroussin tag = *section; 183*40274a2dSBaptiste Daroussin MOVE_TAG(1); 184*40274a2dSBaptiste Daroussin 185*40274a2dSBaptiste Daroussin /* 186*40274a2dSBaptiste Daroussin * These tag values come from: 187*40274a2dSBaptiste Daroussin * 188*40274a2dSBaptiste Daroussin * Addenda to, and Errata in, the ABI for the 189*40274a2dSBaptiste Daroussin * ARM Architecture. Release 2.08, section 2.3. 190*40274a2dSBaptiste Daroussin */ 191*40274a2dSBaptiste Daroussin if (tag == 6) { /* == Tag_CPU_arch */ 192*40274a2dSBaptiste Daroussin uint8_t val; 193*40274a2dSBaptiste Daroussin 194*40274a2dSBaptiste Daroussin val = *section; 195*40274a2dSBaptiste Daroussin /* 196*40274a2dSBaptiste Daroussin * We don't support values that require 197*40274a2dSBaptiste Daroussin * more than one byte. 198*40274a2dSBaptiste Daroussin */ 199*40274a2dSBaptiste Daroussin if (val & (1 << 7)) 200*40274a2dSBaptiste Daroussin return (NULL); 201*40274a2dSBaptiste Daroussin 202*40274a2dSBaptiste Daroussin /* We have an ARMv4 or ARMv5 */ 203*40274a2dSBaptiste Daroussin if (val <= 5) 204*40274a2dSBaptiste Daroussin return ("arm"); 205*40274a2dSBaptiste Daroussin else /* We have an ARMv6+ */ 206*40274a2dSBaptiste Daroussin return ("armv6"); 207*40274a2dSBaptiste Daroussin } else if (tag == 4 || tag == 5 || tag == 32 || 208*40274a2dSBaptiste Daroussin tag == 65 || tag == 67) { 209*40274a2dSBaptiste Daroussin while (*section != '\0' && length != 0) 210*40274a2dSBaptiste Daroussin MOVE_TAG(1); 211*40274a2dSBaptiste Daroussin if (tag_length == 0) 212*40274a2dSBaptiste Daroussin return (NULL); 213*40274a2dSBaptiste Daroussin /* Skip the last byte */ 214*40274a2dSBaptiste Daroussin MOVE_TAG(1); 215*40274a2dSBaptiste Daroussin } else if ((tag >= 7 && tag <= 31) || tag == 34 || 216*40274a2dSBaptiste Daroussin tag == 36 || tag == 38 || tag == 42 || tag == 44 || 217*40274a2dSBaptiste Daroussin tag == 64 || tag == 66 || tag == 68 || tag == 70) { 218*40274a2dSBaptiste Daroussin /* Skip the uleb128 data */ 219*40274a2dSBaptiste Daroussin while (*section & (1 << 7) && length != 0) 220*40274a2dSBaptiste Daroussin MOVE_TAG(1); 221*40274a2dSBaptiste Daroussin if (tag_length == 0) 222*40274a2dSBaptiste Daroussin return (NULL); 223*40274a2dSBaptiste Daroussin /* Skip the last byte */ 224*40274a2dSBaptiste Daroussin MOVE_TAG(1); 225*40274a2dSBaptiste Daroussin } else 226*40274a2dSBaptiste Daroussin return (NULL); 227*40274a2dSBaptiste Daroussin #undef MOVE_TAG 228*40274a2dSBaptiste Daroussin } 229*40274a2dSBaptiste Daroussin 230*40274a2dSBaptiste Daroussin break; 231*40274a2dSBaptiste Daroussin } 232*40274a2dSBaptiste Daroussin return (NULL); 233*40274a2dSBaptiste Daroussin #undef MOVE 234*40274a2dSBaptiste Daroussin } 235*40274a2dSBaptiste 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; 244*40274a2dSBaptiste Daroussin const char *arch, *abi, *fpu, *endian_corres_str; 245*40274a2dSBaptiste 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 314*40274a2dSBaptiste Daroussin wordsize_corres_str = elf_corres_to_string(wordsize_corres, 315*40274a2dSBaptiste Daroussin (int)elfhdr.e_ident[EI_CLASS]); 316*40274a2dSBaptiste Daroussin 317*40274a2dSBaptiste Daroussin arch = elf_corres_to_string(mach_corres, (int) elfhdr.e_machine); 318*40274a2dSBaptiste Daroussin 319*40274a2dSBaptiste Daroussin snprintf(dest, sz, "%s:%d", 320*40274a2dSBaptiste Daroussin osname, version / 100000); 3219950eceeSBaptiste Daroussin 3229950eceeSBaptiste Daroussin ret = 0; 3239950eceeSBaptiste Daroussin 3249950eceeSBaptiste Daroussin switch (elfhdr.e_machine) { 3259950eceeSBaptiste Daroussin case EM_ARM: 326*40274a2dSBaptiste Daroussin endian_corres_str = elf_corres_to_string(endian_corres, 327*40274a2dSBaptiste Daroussin (int)elfhdr.e_ident[EI_DATA]); 328*40274a2dSBaptiste Daroussin 3294b5ef056SBaptiste Daroussin /* FreeBSD doesn't support the hard-float ABI yet */ 3304b5ef056SBaptiste Daroussin fpu = "softfp"; 3314b5ef056SBaptiste Daroussin if ((elfhdr.e_flags & 0xFF000000) != 0) { 332*40274a2dSBaptiste Daroussin const char *sh_name = NULL; 333*40274a2dSBaptiste Daroussin size_t shstrndx; 334*40274a2dSBaptiste Daroussin 3354b5ef056SBaptiste Daroussin /* This is an EABI file, the conformance level is set */ 3364b5ef056SBaptiste Daroussin abi = "eabi"; 337*40274a2dSBaptiste Daroussin /* Find which TARGET_ARCH we are building for. */ 338*40274a2dSBaptiste Daroussin elf_getshdrstrndx(elf, &shstrndx); 339*40274a2dSBaptiste Daroussin while ((scn = elf_nextscn(elf, scn)) != NULL) { 340*40274a2dSBaptiste Daroussin sh_name = NULL; 341*40274a2dSBaptiste Daroussin if (gelf_getshdr(scn, &shdr) != &shdr) { 342*40274a2dSBaptiste Daroussin scn = NULL; 343*40274a2dSBaptiste Daroussin break; 344*40274a2dSBaptiste Daroussin } 345*40274a2dSBaptiste Daroussin 346*40274a2dSBaptiste Daroussin sh_name = elf_strptr(elf, shstrndx, 347*40274a2dSBaptiste Daroussin shdr.sh_name); 348*40274a2dSBaptiste Daroussin if (sh_name == NULL) 349*40274a2dSBaptiste Daroussin continue; 350*40274a2dSBaptiste Daroussin if (strcmp(".ARM.attributes", sh_name) == 0) 351*40274a2dSBaptiste Daroussin break; 352*40274a2dSBaptiste Daroussin } 353*40274a2dSBaptiste Daroussin if (scn != NULL && sh_name != NULL) { 354*40274a2dSBaptiste Daroussin data = elf_getdata(scn, NULL); 355*40274a2dSBaptiste Daroussin /* 356*40274a2dSBaptiste Daroussin * Prior to FreeBSD 10.0 libelf would return 357*40274a2dSBaptiste Daroussin * NULL from elf_getdata on the .ARM.attributes 358*40274a2dSBaptiste Daroussin * section. As this was the first release to 359*40274a2dSBaptiste Daroussin * get armv6 support assume a NULL value means 360*40274a2dSBaptiste Daroussin * arm. 361*40274a2dSBaptiste Daroussin * 362*40274a2dSBaptiste Daroussin * This assumption can be removed when 9.x 363*40274a2dSBaptiste Daroussin * is unsupported. 364*40274a2dSBaptiste Daroussin */ 365*40274a2dSBaptiste Daroussin if (data != NULL) { 366*40274a2dSBaptiste Daroussin arch = aeabi_parse_arm_attributes( 367*40274a2dSBaptiste Daroussin data->d_buf, data->d_size); 368*40274a2dSBaptiste Daroussin if (arch == NULL) { 369*40274a2dSBaptiste Daroussin ret = 1; 370*40274a2dSBaptiste Daroussin warn("unknown ARM ARCH"); 371*40274a2dSBaptiste Daroussin goto cleanup; 372*40274a2dSBaptiste Daroussin } 373*40274a2dSBaptiste Daroussin } 374*40274a2dSBaptiste Daroussin } else { 375*40274a2dSBaptiste Daroussin ret = 1; 376*40274a2dSBaptiste Daroussin warn("Unable to find the .ARM.attributes " 377*40274a2dSBaptiste Daroussin "section"); 378*40274a2dSBaptiste Daroussin goto cleanup; 379*40274a2dSBaptiste 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; 388*40274a2dSBaptiste Daroussin warn("unknown ARM ABI"); 3894b5ef056SBaptiste Daroussin goto cleanup; 3904b5ef056SBaptiste Daroussin } 3919950eceeSBaptiste Daroussin snprintf(dest + strlen(dest), sz - strlen(dest), 392*40274a2dSBaptiste Daroussin ":%s:%s:%s:%s:%s", arch, wordsize_corres_str, 393*40274a2dSBaptiste 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 } 418*40274a2dSBaptiste Daroussin endian_corres_str = elf_corres_to_string(endian_corres, 419*40274a2dSBaptiste Daroussin (int)elfhdr.e_ident[EI_DATA]); 420*40274a2dSBaptiste Daroussin 421*40274a2dSBaptiste Daroussin snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s:%s:%s", 422*40274a2dSBaptiste Daroussin arch, wordsize_corres_str, endian_corres_str, abi); 4239950eceeSBaptiste Daroussin break; 424*40274a2dSBaptiste Daroussin default: 425*40274a2dSBaptiste Daroussin snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s", 426*40274a2dSBaptiste 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) 5519950eceeSBaptiste Daroussin err(EXIT_FAILURE, "Unable to open configuration file %s", confpath); 5529950eceeSBaptiste Daroussin /* no configuration present */ 5539950eceeSBaptiste Daroussin goto finalize; 5549950eceeSBaptiste Daroussin } 5559950eceeSBaptiste Daroussin 5569950eceeSBaptiste Daroussin yaml_parser_initialize(&parser); 5579950eceeSBaptiste Daroussin yaml_parser_set_input_file(&parser, fp); 5589950eceeSBaptiste Daroussin yaml_parser_load(&parser, &doc); 5599950eceeSBaptiste Daroussin 5609950eceeSBaptiste Daroussin node = yaml_document_get_root_node(&doc); 5619950eceeSBaptiste Daroussin 5629950eceeSBaptiste Daroussin if (node != NULL) { 5639950eceeSBaptiste Daroussin if (node->type != YAML_MAPPING_NODE) 5649950eceeSBaptiste Daroussin warnx("Invalid configuration format, ignoring the configuration file"); 5659950eceeSBaptiste Daroussin else 5669950eceeSBaptiste Daroussin config_parse(&doc, node); 5679950eceeSBaptiste Daroussin } else { 5689950eceeSBaptiste Daroussin warnx("Invalid configuration format, ignoring the configuration file"); 5699950eceeSBaptiste Daroussin } 5709950eceeSBaptiste Daroussin 5719950eceeSBaptiste Daroussin yaml_document_delete(&doc); 5729950eceeSBaptiste Daroussin yaml_parser_delete(&parser); 5739950eceeSBaptiste Daroussin 5749950eceeSBaptiste Daroussin finalize: 5759950eceeSBaptiste Daroussin if (c[ABI].val == NULL && c[ABI].value == NULL) { 5769950eceeSBaptiste Daroussin if (pkg_get_myabi(abi, BUFSIZ) != 0) 5779950eceeSBaptiste Daroussin errx(EXIT_FAILURE, "Failed to determine the system ABI"); 5789950eceeSBaptiste Daroussin c[ABI].val = abi; 5799950eceeSBaptiste Daroussin } 5809950eceeSBaptiste Daroussin 581d5bf8a8bSBaptiste Daroussin subst_packagesite(c[ABI].value != NULL ? c[ABI].value : c[ABI].val); 5829950eceeSBaptiste Daroussin 5839950eceeSBaptiste Daroussin return (0); 5849950eceeSBaptiste Daroussin } 5859950eceeSBaptiste Daroussin 5869950eceeSBaptiste Daroussin int 5879950eceeSBaptiste Daroussin config_string(pkg_config_key k, const char **val) 5889950eceeSBaptiste Daroussin { 5899950eceeSBaptiste Daroussin if (c[k].type != PKG_CONFIG_STRING) 5909950eceeSBaptiste Daroussin return (-1); 5919950eceeSBaptiste Daroussin 5929950eceeSBaptiste Daroussin if (c[k].value != NULL) 5939950eceeSBaptiste Daroussin *val = c[k].value; 5949950eceeSBaptiste Daroussin else 5959950eceeSBaptiste Daroussin *val = c[k].val; 5969950eceeSBaptiste Daroussin 5979950eceeSBaptiste Daroussin return (0); 5989950eceeSBaptiste Daroussin } 5999950eceeSBaptiste Daroussin 6009950eceeSBaptiste Daroussin int 6019950eceeSBaptiste Daroussin config_bool(pkg_config_key k, bool *val) 6029950eceeSBaptiste Daroussin { 6039950eceeSBaptiste Daroussin const char *value; 6049950eceeSBaptiste Daroussin 6059950eceeSBaptiste Daroussin if (c[k].type != PKG_CONFIG_BOOL) 6069950eceeSBaptiste Daroussin return (-1); 6079950eceeSBaptiste Daroussin 6089950eceeSBaptiste Daroussin *val = false; 6099950eceeSBaptiste Daroussin 6109950eceeSBaptiste Daroussin if (c[k].value != NULL) 6119950eceeSBaptiste Daroussin value = c[k].value; 6129950eceeSBaptiste Daroussin else 6139950eceeSBaptiste Daroussin value = c[k].val; 6149950eceeSBaptiste Daroussin 6159950eceeSBaptiste Daroussin if (strcasecmp(value, "true") == 0 || 6169950eceeSBaptiste Daroussin strcasecmp(value, "yes") == 0 || 6179950eceeSBaptiste Daroussin strcasecmp(value, "on") == 0 || 6189950eceeSBaptiste Daroussin *value == '1') 6199950eceeSBaptiste Daroussin *val = true; 6209950eceeSBaptiste Daroussin 6219950eceeSBaptiste Daroussin return (0); 6229950eceeSBaptiste Daroussin } 6239950eceeSBaptiste Daroussin 6249950eceeSBaptiste Daroussin void 6259950eceeSBaptiste Daroussin config_finish(void) { 6269950eceeSBaptiste Daroussin int i; 6279950eceeSBaptiste Daroussin 6289950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) 6299950eceeSBaptiste Daroussin free(c[i].value); 6309950eceeSBaptiste Daroussin } 631