1 /* 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 
22 void
__go_fieldtrack(byte * p)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 
30 extern const char _etext[] __attribute__ ((weak));
31 extern const char __etext[] __attribute__ ((weak));
32 extern const char __data_start[] __attribute__ ((weak));
33 extern const char _edata[] __attribute__ ((weak));
34 extern const char __edata[] __attribute__ ((weak));
35 extern const char __bss_start[] __attribute__ ((weak));
36 
37 void runtime_Fieldtrack (struct __go_map *) __asm__ (GOSYM_PREFIX "runtime.Fieldtrack");
38 
39 void
runtime_Fieldtrack(struct __go_map * m)40 runtime_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 }
102