check_type: fix incorrect documentation.
[ccan] / ccan / autodata / autodata.c
1 // Licensed under BSD-MIT: See LICENSE.
2 #include "autodata.h"
3 #include <stdint.h>
4 #include <unistd.h>
5 #include <string.h>
6
7 #if HAVE_SECTION_START_STOP
8 void *autodata_get_section(void *start, void *stop, size_t *nump)
9 {
10         *nump = (void **)(stop) - (void **)(start);
11         return start;
12 }
13
14 void autodata_free(void *table)
15 {
16 }
17 #else
18 #include <ccan/ptr_valid/ptr_valid.h>
19
20 void *autodata_make_table(const void *example, const char *name, size_t *nump)
21 {
22         const char *start, *end, *tag;
23         struct ptr_valid_batch batch;
24         const void *const magic = (void *)AUTODATA_MAGIC;
25         void **table = NULL;
26         char first_magic;
27
28         if (!ptr_valid_batch_start(&batch))
29                 return NULL;
30
31         /* Get range to search. */
32         for (start = (char *)((intptr_t)example & ~(getpagesize() - 1));
33              ptr_valid_batch(&batch, start-getpagesize(), 1, sizeof(void *),
34                              false);
35              start -= getpagesize());
36
37         for (end = (char *)((intptr_t)example & ~(getpagesize() - 1));
38              ptr_valid_batch(&batch, end, 1, sizeof(void *), false);
39              end += getpagesize());
40
41         *nump = 0;
42         first_magic = *(char *)&magic;
43         for (tag = memchr(start, first_magic, end - start);
44              tag;
45              tag = memchr(tag+1, first_magic, end - (tag + 1))) {
46                 void *adata[4];
47
48                 /* We can read 4 void *'s here? */
49                 if (tag + sizeof(adata) > end)
50                         continue;
51
52                 memcpy(adata, tag, sizeof(adata));
53
54                 /* False match? */
55                 if (adata[0] != (void *)AUTODATA_MAGIC || adata[1] != tag)
56                         continue;
57
58                 /* OK, check name. */
59                 if (!ptr_valid_batch_string(&batch, adata[3])
60                     || strcmp(name, adata[3]) != 0)
61                         continue;
62
63                 if (!ptr_valid_batch_read(&batch, (char *)adata[2]))
64                         continue;
65
66                 table = realloc(table, sizeof(void *) * (*nump + 1));
67                 if (!table)
68                         break;
69                 table[*nump] = adata[2];
70                 (*nump)++;
71         }
72         ptr_valid_batch_end(&batch);
73         return table;
74 }
75
76 void autodata_free(void *table)
77 {
78         free(table);
79 }
80 #endif