2 * Copyright (c) 2013 Baptiste Daroussin <bapt@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/param.h>
32 #include <sys/elf_common.h>
33 #include <sys/endian.h>
48 #include "elf_tables.h"
51 #define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
61 static struct config_entry c[] = {
65 "http://pkg.FreeBSD.org/${ABI}/latest",
83 [ASSUME_ALWAYS_YES] = {
93 elf_corres_to_string(struct _elf_corres *m, int e)
97 for (i = 0; m[i].string != NULL; i++)
105 aeabi_parse_arm_attributes(void *data, size_t length)
108 uint8_t *section = data;
110 #define MOVE(len) do { \
111 assert(length >= (len)); \
116 if (length == 0 || *section != 'A')
121 /* Read the section length */
122 if (length < sizeof(sect_len))
125 memcpy(§_len, section, sizeof(sect_len));
128 * The section length should be no longer than the section it is within
130 if (sect_len > length)
133 MOVE(sizeof(sect_len));
135 /* Skip the vendor name */
136 while (length != 0) {
137 if (*section == '\0')
145 while (length != 0) {
149 case 1: /* Tag_File */
151 if (length < sizeof(tag_length))
153 memcpy(&tag_length, section, sizeof(tag_length));
155 case 2: /* Tag_Section */
156 case 3: /* Tag_Symbol */
160 /* At least space for the tag and size */
164 /* Check the tag fits */
165 if (tag_length > length)
168 #define MOVE_TAG(len) do { \
169 assert(tag_length >= (len)); \
171 tag_length -= (len); \
174 MOVE(sizeof(tag_length));
175 tag_length -= sizeof(tag_length);
177 while (tag_length != 0) {
180 assert(tag_length >= length);
186 * These tag values come from:
188 * Addenda to, and Errata in, the ABI for the
189 * ARM Architecture. Release 2.08, section 2.3.
191 if (tag == 6) { /* == Tag_CPU_arch */
196 * We don't support values that require
197 * more than one byte.
202 /* We have an ARMv4 or ARMv5 */
205 else /* We have an ARMv6+ */
207 } else if (tag == 4 || tag == 5 || tag == 32 ||
208 tag == 65 || tag == 67) {
209 while (*section != '\0' && length != 0)
213 /* Skip the last byte */
215 } else if ((tag >= 7 && tag <= 31) || tag == 34 ||
216 tag == 36 || tag == 38 || tag == 42 || tag == 44 ||
217 tag == 64 || tag == 66 || tag == 68 || tag == 70) {
218 /* Skip the uleb128 data */
219 while (*section & (1 << 7) && length != 0)
223 /* Skip the last byte */
237 pkg_get_myabi(char *dest, size_t sz)
244 const char *arch, *abi, *fpu, *endian_corres_str;
245 const char *wordsize_corres_str;
256 if (elf_version(EV_CURRENT) == EV_NONE) {
257 warnx("ELF library initialization failed: %s",
262 if ((fd = open(_PATH_BSHELL, O_RDONLY)) < 0) {
267 if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
269 warnx("elf_begin() failed: %s.", elf_errmsg(-1));
273 if (gelf_getehdr(elf, &elfhdr) == NULL) {
275 warn("getehdr() failed: %s.", elf_errmsg(-1));
278 while ((scn = elf_nextscn(elf, scn)) != NULL) {
279 if (gelf_getshdr(scn, &shdr) != &shdr) {
281 warn("getshdr() failed: %s.", elf_errmsg(-1));
285 if (shdr.sh_type == SHT_NOTE)
291 warn("failed to get the note section");
295 data = elf_getdata(scn, NULL);
298 memcpy(¬e, src, sizeof(Elf_Note));
299 src += sizeof(Elf_Note);
300 if (note.n_type == NT_VERSION)
302 src += note.n_namesz + note.n_descsz;
305 src += roundup2(note.n_namesz, 4);
306 if (elfhdr.e_ident[EI_DATA] == ELFDATA2MSB)
307 version = be32dec(src);
309 version = le32dec(src);
311 for (i = 0; osname[i] != '\0'; i++)
312 osname[i] = (char)tolower(osname[i]);
314 wordsize_corres_str = elf_corres_to_string(wordsize_corres,
315 (int)elfhdr.e_ident[EI_CLASS]);
317 arch = elf_corres_to_string(mach_corres, (int) elfhdr.e_machine);
319 snprintf(dest, sz, "%s:%d",
320 osname, version / 100000);
324 switch (elfhdr.e_machine) {
326 endian_corres_str = elf_corres_to_string(endian_corres,
327 (int)elfhdr.e_ident[EI_DATA]);
329 /* FreeBSD doesn't support the hard-float ABI yet */
331 if ((elfhdr.e_flags & 0xFF000000) != 0) {
332 const char *sh_name = NULL;
335 /* This is an EABI file, the conformance level is set */
337 /* Find which TARGET_ARCH we are building for. */
338 elf_getshdrstrndx(elf, &shstrndx);
339 while ((scn = elf_nextscn(elf, scn)) != NULL) {
341 if (gelf_getshdr(scn, &shdr) != &shdr) {
346 sh_name = elf_strptr(elf, shstrndx,
350 if (strcmp(".ARM.attributes", sh_name) == 0)
353 if (scn != NULL && sh_name != NULL) {
354 data = elf_getdata(scn, NULL);
356 * Prior to FreeBSD 10.0 libelf would return
357 * NULL from elf_getdata on the .ARM.attributes
358 * section. As this was the first release to
359 * get armv6 support assume a NULL value means
362 * This assumption can be removed when 9.x
366 arch = aeabi_parse_arm_attributes(
367 data->d_buf, data->d_size);
370 warn("unknown ARM ARCH");
376 warn("Unable to find the .ARM.attributes "
380 } else if (elfhdr.e_ident[EI_OSABI] != ELFOSABI_NONE) {
382 * EABI executables all have this field set to
383 * ELFOSABI_NONE, therefore it must be an oabi file.
388 warn("unknown ARM ABI");
391 snprintf(dest + strlen(dest), sz - strlen(dest),
392 ":%s:%s:%s:%s:%s", arch, wordsize_corres_str,
393 endian_corres_str, abi, fpu);
397 * this is taken from binutils sources:
399 * mapping is figured out from binutils:
400 * gas/config/tc-mips.c
402 switch (elfhdr.e_flags & EF_MIPS_ABI) {
410 if (elfhdr.e_ident[EI_DATA] ==
413 else if (elfhdr.e_ident[EI_DATA] ==
418 endian_corres_str = elf_corres_to_string(endian_corres,
419 (int)elfhdr.e_ident[EI_DATA]);
421 snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s:%s:%s",
422 arch, wordsize_corres_str, endian_corres_str, abi);
425 snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s",
426 arch, wordsize_corres_str);
438 subst_packagesite(const char *abi)
441 const char *variable_string;
444 if (c[PACKAGESITE].value != NULL)
445 oldval = c[PACKAGESITE].value;
447 oldval = c[PACKAGESITE].val;
449 if ((variable_string = strstr(oldval, "${ABI}")) == NULL)
452 newval = sbuf_new_auto();
453 sbuf_bcat(newval, oldval, variable_string - oldval);
454 sbuf_cat(newval, abi);
455 sbuf_cat(newval, variable_string + strlen("${ABI}"));
458 free(c[PACKAGESITE].value);
459 c[PACKAGESITE].value = strdup(sbuf_data(newval));
463 config_parse(yaml_document_t *doc, yaml_node_t *node)
465 yaml_node_pair_t *pair;
466 yaml_node_t *key, *val;
467 struct sbuf *buf = sbuf_new_auto();
471 pair = node->data.mapping.pairs.start;
473 while (pair < node->data.mapping.pairs.top) {
474 key = yaml_document_get_node(doc, pair->key);
475 val = yaml_document_get_node(doc, pair->value);
478 * ignoring silently empty keys can be empty lines
481 if (key->data.scalar.length <= 0) {
487 * silently skip on purpose to allow user to leave
488 * empty lines without complaining
490 if (val->type == YAML_NO_NODE ||
491 (val->type == YAML_SCALAR_NODE &&
492 val->data.scalar.length <= 0)) {
498 for (j = 0; j < strlen(key->data.scalar.value); ++j)
499 sbuf_putc(buf, toupper(key->data.scalar.value[j]));
502 for (i = 0; i < CONFIG_SIZE; i++) {
503 if (strcmp(sbuf_data(buf), c[i].key) == 0)
507 if (i == CONFIG_SIZE) {
512 /* env has priority over config file */
518 c[i].value = strdup(val->data.scalar.value);
529 yaml_parser_t parser;
534 const char *localbase;
535 char confpath[MAXPATHLEN];
538 for (i = 0; i < CONFIG_SIZE; i++) {
539 val = getenv(c[i].key);
546 localbase = getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE;
547 snprintf(confpath, sizeof(confpath), "%s/etc/pkg.conf", localbase);
549 if ((fp = fopen(confpath, "r")) == NULL) {
551 err(EXIT_FAILURE, "Unable to open configuration file %s", confpath);
552 /* no configuration present */
556 yaml_parser_initialize(&parser);
557 yaml_parser_set_input_file(&parser, fp);
558 yaml_parser_load(&parser, &doc);
560 node = yaml_document_get_root_node(&doc);
563 if (node->type != YAML_MAPPING_NODE)
564 warnx("Invalid configuration format, ignoring the configuration file");
566 config_parse(&doc, node);
568 warnx("Invalid configuration format, ignoring the configuration file");
571 yaml_document_delete(&doc);
572 yaml_parser_delete(&parser);
575 if (c[ABI].val == NULL && c[ABI].value == NULL) {
576 if (pkg_get_myabi(abi, BUFSIZ) != 0)
577 errx(EXIT_FAILURE, "Failed to determine the system ABI");
581 subst_packagesite(c[ABI].value != NULL ? c[ABI].value : c[ABI].val);
587 config_string(pkg_config_key k, const char **val)
589 if (c[k].type != PKG_CONFIG_STRING)
592 if (c[k].value != NULL)
601 config_bool(pkg_config_key k, bool *val)
605 if (c[k].type != PKG_CONFIG_BOOL)
610 if (c[k].value != NULL)
615 if (strcasecmp(value, "true") == 0 ||
616 strcasecmp(value, "yes") == 0 ||
617 strcasecmp(value, "on") == 0 ||
625 config_finish(void) {
628 for (i = 0; i < CONFIG_SIZE; i++)