| /* go-fieldtrack.c -- structure field data analysis. | 
 |  | 
 |    Copyright 2012 The Go Authors. All rights reserved. | 
 |    Use of this source code is governed by a BSD-style | 
 |    license that can be found in the LICENSE file.  */ | 
 |  | 
 | #include "runtime.h" | 
 |  | 
 | /* The compiler will track fields that have the tag go:"track".  Any | 
 |    function that refers to such a field will call this function with a | 
 |    string | 
 |        fieldtrack "package.type.field" | 
 |  | 
 |    This function does not actually do anything.  Instead, we gather | 
 |    the field tracking information by looking for strings of that form | 
 |    in the read-only data section.  This is, of course, a horrible | 
 |    hack, but it's good enough for now.  We can improve it, e.g., by a | 
 |    linker plugin, if this turns out to be useful.  */ | 
 |  | 
 | void | 
 | __go_fieldtrack (byte *p __attribute__ ((unused))) | 
 | { | 
 | } | 
 |  | 
 | /* A runtime function to add all the tracked fields to a | 
 |    map[string]bool.  */ | 
 |  | 
 | extern void *mapassign (const struct maptype *, void *hmap, const void *key) | 
 |   __asm__ (GOSYM_PREFIX "runtime.mapassign"); | 
 |  | 
 | // The type descriptor for map[string] bool.  */ | 
 | extern const char map_string_bool[] __attribute__ ((weak)); | 
 | extern const char map_string_bool[] | 
 |   __asm__ (GOSYM_PREFIX "type..map_6string_7bool"); | 
 |  | 
 | void runtime_Fieldtrack (void *) __asm__ (GOSYM_PREFIX "runtime.Fieldtrack"); | 
 |  | 
 | void | 
 | runtime_Fieldtrack (void *m) | 
 | { | 
 |   const char *p; | 
 |   const char *pend; | 
 |   const char *prefix; | 
 |   size_t prefix_len; | 
 |  | 
 |   if (map_string_bool == NULL) | 
 |     return; | 
 |  | 
 |   p = __data_start; | 
 |   if (p == NULL) | 
 |     p = __etext; | 
 |   if (p == NULL) | 
 |     p = _etext; | 
 |   if (p == NULL) | 
 |     return; | 
 |  | 
 |   pend = __edata; | 
 |   if (pend == NULL) | 
 |     pend = _edata; | 
 |   if (pend == NULL) | 
 |     pend = __bss_start; | 
 |   if (pend == NULL) | 
 |     return; | 
 |  | 
 |   prefix = "fieldtrack "; | 
 |   prefix_len = __builtin_strlen (prefix); | 
 |  | 
 |   while (p < pend) | 
 |     { | 
 |       const char *q1; | 
 |       const char *q2; | 
 |  | 
 |       q1 = __builtin_memchr (p + prefix_len, '"', pend - (p + prefix_len)); | 
 |       if (q1 == NULL) | 
 | 	break; | 
 |  | 
 |       if (__builtin_memcmp (q1 - prefix_len, prefix, prefix_len) != 0) | 
 | 	{ | 
 | 	  p = q1 + 1; | 
 | 	  continue; | 
 | 	} | 
 |  | 
 |       q1++; | 
 |       q2 = __builtin_memchr (q1, '"', pend - q1); | 
 |       if (q2 == NULL) | 
 | 	break; | 
 |  | 
 |       if (__builtin_memchr (q1, '\0', q2 - q1) == NULL) | 
 | 	{ | 
 | 	  String s; | 
 | 	  void *p; | 
 |  | 
 | 	  s.str = (const byte *) q1; | 
 | 	  s.len = q2 - q1; | 
 | 	  p = mapassign((const void*) map_string_bool, m, &s); | 
 | 	  *(_Bool*)p = 1; | 
 | 	} | 
 |  | 
 |       p = q2; | 
 |     } | 
 | } |