blob: a7e2c133440e17685ad4144802c93f4a8e35628d [file] [log] [blame]
Peter Collingbourne594c10d2014-11-27 00:12:26 +00001/* go-fieldtrack.c -- structure field data analysis.
2
3 Copyright 2012 The Go Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style
5 license that can be found in the LICENSE file. */
6
7#include "runtime.h"
8#include "go-type.h"
9#include "map.h"
10
11/* The compiler will track fields that have the tag go:"track". Any
12 function that refers to such a field will call this function with a
13 string
14 fieldtrack "package.type.field"
15
16 This function does not actually do anything. Instead, we gather
17 the field tracking information by looking for strings of that form
18 in the read-only data section. This is, of course, a horrible
19 hack, but it's good enough for now. We can improve it, e.g., by a
20 linker plugin, if this turns out to be useful. */
21
22void
23__go_fieldtrack (byte *p __attribute__ ((unused)))
24{
25}
26
27/* A runtime function to add all the tracked fields to a
28 map[string]bool. */
29
30extern const char _etext[] __attribute__ ((weak));
31extern const char __etext[] __attribute__ ((weak));
32extern const char __data_start[] __attribute__ ((weak));
33extern const char _edata[] __attribute__ ((weak));
34extern const char __edata[] __attribute__ ((weak));
35extern const char __bss_start[] __attribute__ ((weak));
36
37void runtime_Fieldtrack (struct __go_map *) __asm__ (GOSYM_PREFIX "runtime.Fieldtrack");
38
39void
40runtime_Fieldtrack (struct __go_map *m)
41{
42 const char *p;
43 const char *pend;
44 const char *prefix;
45 size_t prefix_len;
46
47 p = __data_start;
48 if (p == NULL)
49 p = __etext;
50 if (p == NULL)
51 p = _etext;
52 if (p == NULL)
53 return;
54
55 pend = __edata;
56 if (pend == NULL)
57 pend = _edata;
58 if (pend == NULL)
59 pend = __bss_start;
60 if (pend == NULL)
61 return;
62
63 prefix = "fieldtrack ";
64 prefix_len = __builtin_strlen (prefix);
65
66 while (p < pend)
67 {
68 const char *q1;
69 const char *q2;
70
71 q1 = __builtin_memchr (p + prefix_len, '"', pend - (p + prefix_len));
72 if (q1 == NULL)
73 break;
74
75 if (__builtin_memcmp (q1 - prefix_len, prefix, prefix_len) != 0)
76 {
77 p = q1 + 1;
78 continue;
79 }
80
81 q1++;
82 q2 = __builtin_memchr (q1, '"', pend - q1);
83 if (q2 == NULL)
84 break;
85
86 if (__builtin_memchr (q1, '\0', q2 - q1) == NULL)
87 {
88 String s;
89 void *v;
90 _Bool *pb;
91
92 s.str = (const byte *) q1;
93 s.len = q2 - q1;
94 v = __go_map_index (m, &s, 1);
95 pb = (_Bool *) v;
96 *pb = 1;
97 }
98
99 p = q2;
100 }
101}