1 /* The meat of this file is a copy of the FreeBSD sys/link_set.h */
   2 /*
   3  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
   4  *
   5  * Copyright (c) 1999 John D. Polstra
   6  * Copyright (c) 1999,2001 Peter Wemm <peter@FreeBSD.org>
   7  * All rights reserved.
   8  *
   9  * Redistribution and use in source and binary forms, with or without
  10  * modification, are permitted provided that the following conditions
  11  * are met:
  12  * 1. Redistributions of source code must retain the above copyright
  13  *    notice, this list of conditions and the following disclaimer.
  14  * 2. Redistributions in binary form must reproduce the above copyright
  15  *    notice, this list of conditions and the following disclaimer in the
  16  *    documentation and/or other materials provided with the distribution.
  17  *
  18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28  * SUCH DAMAGE.
  29  *
  30  * $FreeBSD$
  31  */
  32 
  33 #include <stdio.h>
  34 
  35 #define MAKE_SET(set, sym)                                      \
  36         __asm__(".globl __start_set_" #set);                    \
  37         __asm__(".globl __stop_set_" #set);                     \
  38         static __attribute__((section("set_" #set), used))      \
  39         void const *__set_##set##_sym_##sym = &(sym)
  40 
  41 /*
  42  * Initialize before referring to a given linker set.
  43  */
  44 #define SET_DECLARE(set, ptype)                                         \
  45         extern  __attribute__((weak)) ptype *__start_set_ ## set;       \
  46         extern __attribute__((weak)) ptype *__stop_set_ ## set
  47 
  48 #define SET_BEGIN(set)  (&__start_set_ ## set)
  49 #define SET_LIMIT(set)  (&__stop_set_ ## set)
  50 
  51 /*
  52  * Iterate over all the elements of a set.
  53  *
  54  * Sets always contain addresses of things, and "pvar" points to words
  55  * containing those addresses.  Thus is must be declared as "type **pvar",
  56  * and the address of each set item is obtained inside the loop by "*pvar".
  57  */
  58 #define SET_FOREACH(pvar, set)                                          \
  59         for (pvar = SET_BEGIN(set); pvar < SET_LIMIT(set); pvar++)
  60 
  61 #define SET_ITEM(set, i)                                                \
  62         ((SET_BEGIN(set))[i])
  63 
  64 /*
  65  * Provide a count of the items in a set.
  66  */
  67 #define SET_COUNT(set)                                                  \
  68         (SET_LIMIT(set) - SET_BEGIN(set))
  69 
  70 struct foo {
  71         char buf[128];
  72 };
  73 
  74 SET_DECLARE(foo, struct foo);
  75 
  76 struct foo a = { "foo" };
  77 struct foo b = { "bar" };
  78 struct foo c = { "baz" };
  79 
  80 MAKE_SET(foo, a);
  81 MAKE_SET(foo, b);
  82 MAKE_SET(foo, c);
  83 
  84 int
  85 main(int __attribute__((unused)) argc, char __attribute__((unused)) **argv)
  86 {
  87         struct foo **c;
  88         int i = 0;
  89 
  90         printf("Set count: %d\n", SET_COUNT(foo));
  91 
  92 
  93         printf("a: %s\n", ((struct foo *)__set_foo_sym_a)->buf);
  94         printf("b: %s\n", ((struct foo *)__set_foo_sym_b)->buf);
  95         printf("c: %s\n", ((struct foo *)__set_foo_sym_c)->buf);
  96 
  97         printf("item(foo, 0): %s\n", SET_ITEM(foo, 0)->buf);
  98         printf("item(foo, 1): %s\n", SET_ITEM(foo, 1)->buf);
  99         printf("item(foo, 2): %s\n", SET_ITEM(foo, 2)->buf);
 100 
 101         SET_FOREACH(c, foo) {
 102                 printf("foo[%d]: %s\n", i, (*c)->buf);
 103                 i++;
 104         }
 105 }