autodata: stash pointers in a binary.
[ccan] / ccan / autodata / autodata.h
1 // Licensed under BSD-MIT: See LICENSE.
2 #ifndef CCAN_AUTODATA_H
3 #define CCAN_AUTODATA_H
4 #include "config.h"
5 #include <ccan/compiler/compiler.h>
6 #include <stdlib.h>
7
8 #if HAVE_SECTION_START_STOP
9
10 /**
11  * AUTODATA_TYPE - declare the type for a given autodata name.
12  * @name: the name for this set of autodata
13  * @type: the type this autodata points to
14  *
15  * This macro is usually placed in a header: it must preceed any
16  * autodata functions in the file.
17  *
18  * Example:
19  *      // My set of char pointers.
20  *      AUTODATA_TYPE(names, char);
21  */
22 #define AUTODATA_TYPE(name, type)                                       \
23         typedef type autodata_##name##_;                                \
24         extern type *__start_autodata_##name[], *__stop_autodata_##name[]
25
26 /**
27  * AUTODATA - add a pointer to this autodata set
28  * @name: the name of the set of autodata
29  * @ptr: the compile-time-known pointer
30  *
31  * This embeds @ptr into the binary, with the tag corresponding to
32  * @name (which must look like a valid identifier, no punctuation!).
33  * The type of @ptr must match that given by AUTODATA_TYPE.  It is
34  * usually a file-level declaration.
35  *
36  * Example:
37  *      // Put two char pointers into the names AUTODATA set.
38  *      AUTODATA(names, "Arabella");
39  *      AUTODATA(names, "Alex");
40  */
41 #define AUTODATA(name, ptr) \
42         static const autodata_##name##_ *NEEDED         \
43         __attribute__((section("autodata_" #name)))     \
44         AUTODATA_VAR_(name, __LINE__) = (ptr);
45
46 /**
47  * autodata_get - get an autodata set
48  * @name: the name of the set of autodata
49  * @nump: the number of items in the set.
50  *
51  * This extract the embedded pointers matching @name.  It may fail
52  * if malloc() fails, or if there is no AUTODATA at all.
53  *
54  * The return will be a pointer to an array of @type pointers (from
55  * AUTODATA_TYPE).
56  *
57  * Example:
58  *      static void print_embedded_names(void)
59  *      {
60  *              unsigned int i, num;
61  *              char **n = autodata_get(names, &num);
62  *
63  *              for (i = 0; i < num; i++)
64  *                      printf("%s\n", n[i]);
65  *      }
66  */
67 #define autodata_get(name, nump)                                        \
68         ((autodata_##name##_ **)                                        \
69          autodata_get_section(__start_autodata_##name,                  \
70                               __stop_autodata_##name, (nump)))
71 #endif /* HAVE_SECTION_START_STOP */
72
73 /**
74  * autodata_free - free the table returned by autodata_get()
75  * @p: the table.
76  */
77 void autodata_free(void *p);
78
79 /* Internal functions. */
80 #define AUTODATA_VAR__(name, line) autodata_##name##_##line
81 #define AUTODATA_VAR_(name, line) AUTODATA_VAR__(name, line)
82
83 #if HAVE_SECTION_START_STOP
84 void *autodata_get_section(void *start, void *stop, size_t *nump);
85 #else
86 #define AUTODATA_TYPE(name, type)                                       \
87         typedef type autodata_##name##_;                                \
88         static const void *autodata_##name##_ex = &autodata_##name##_ex
89
90 #define AUTODATA_MAGIC ((long)0xFEEDA10DA7AF00D5ULL)
91 #define AUTODATA(name, ptr)                                             \
92         static const autodata_##name##_ *NEEDED                         \
93         AUTODATA_VAR_(name, __LINE__)[4] =                              \
94         { (void *)AUTODATA_MAGIC,                                       \
95           (void *)&AUTODATA_VAR_(name, __LINE__),                       \
96           (ptr),                                                        \
97           (void *)#name }
98
99 #define autodata_get(name, nump)                                        \
100         ((autodata_##name##_ **)                                        \
101          autodata_make_table(&autodata_##name##_ex, #name, (nump)))
102
103 void *autodata_make_table(const void *example, const char *name, size_t *nump);
104 #endif
105
106 #endif /* CCAN_AUTODATA_H */