1#!/bin/sh
2
3# Copyright 2016 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# Create runtime_sysinfo.go from gen-sysinfo.go and errno.i.
8
9OUT=tmp-runtime_sysinfo.go
10
11set -e
12
13echo 'package runtime' > ${OUT}
14
15# Get all the consts and types, skipping ones which could not be
16# represented in Go and ones which we need to rewrite.  We also skip
17# function declarations, as we don't need them here.  All the symbols
18# will all have a leading underscore.
19grep -v '^// ' gen-sysinfo.go | \
20  grep -v '^func' | \
21  grep -v '^var ' | \
22  grep -v '^type _timeval ' | \
23  grep -v '^type _timespec_t ' | \
24  grep -v '^type _timespec ' | \
25  grep -v '^type _epoll_' | \
26  grep -v '^type _*locale[_ ]' | \
27  grep -v 'in6_addr' | \
28  grep -v 'sockaddr_in6' | \
29  sed -e 's/\([^a-zA-Z0-9_]\)_timeval\([^a-zA-Z0-9_]\)/\1timeval\2/g' \
30      -e 's/\([^a-zA-Z0-9_]\)_timespec_t\([^a-zA-Z0-9_]\)/\1timespec\2/g' \
31      -e 's/\([^a-zA-Z0-9_]\)_timespec\([^a-zA-Z0-9_]\)/\1timespec\2/g' \
32    >> ${OUT}
33
34# The C long type, needed because that is the type that ptrace returns.
35sizeof_long=`grep '^const ___SIZEOF_LONG__ = ' gen-sysinfo.go | sed -e 's/.*= //'`
36if test "$sizeof_long" = "4"; then
37  echo "type _C_long int32" >> ${OUT}
38  echo "type _C_ulong uint32" >> ${OUT}
39elif test "$sizeof_long" = "8"; then
40  echo "type _C_long int64" >> ${OUT}
41  echo "type _C_ulong uint64" >> ${OUT}
42else
43  echo 1>&2 "mkrsysinfo.sh: could not determine size of long (got $sizeof_long)"
44  exit 1
45fi
46
47# On AIX, the _arpcom struct, is filtered by the above grep sequence, as it as
48# a field of type _in6_addr, but other types depend on _arpcom, so we need to
49# put it back.
50grep '^type _arpcom ' gen-sysinfo.go | \
51  sed -e 's/_in6_addr/[16]byte/' >> ${OUT}
52
53# Same on Solaris for _mld_hdr_t.
54grep '^type _mld_hdr_t ' gen-sysinfo.go | \
55  sed -e 's/_in6_addr/[16]byte/' >> ${OUT}
56
57# The time structures need special handling: we need to name the
58# types, so that we can cast integers to the right types when
59# assigning to the structures.
60timeval=`grep '^type _timeval ' gen-sysinfo.go`
61timeval_sec=`echo $timeval | sed -n -e 's/^.*tv_sec \([^ ]*\);.*$/\1/p'`
62timeval_usec=`echo $timeval | sed -n -e 's/^.*tv_usec \([^ ]*\);.*$/\1/p'`
63echo "type timeval_sec_t $timeval_sec" >> ${OUT}
64echo "type timeval_usec_t $timeval_usec" >> ${OUT}
65echo $timeval | \
66  sed -e 's/type _timeval /type timeval /' \
67      -e 's/tv_sec *[a-zA-Z0-9_]*/tv_sec timeval_sec_t/' \
68      -e 's/tv_usec *[a-zA-Z0-9_]*/tv_usec timeval_usec_t/' >> ${OUT}
69echo >> ${OUT}
70echo "func (tv *timeval) set_usec(x int32) {" >> ${OUT}
71echo "	tv.tv_usec = timeval_usec_t(x)" >> ${OUT}
72echo "}" >> ${OUT}
73
74timespec=`grep '^type _timespec ' gen-sysinfo.go || true`
75if test "$timespec" = ""; then
76  # IRIX 6.5 has __timespec instead.
77  timespec=`grep '^type ___timespec ' gen-sysinfo.go || true`
78fi
79timespec_sec=`echo $timespec | sed -n -e 's/^.*tv_sec \([^ ]*\);.*$/\1/p'`
80timespec_nsec=`echo $timespec | sed -n -e 's/^.*tv_nsec \([^ ]*\);.*$/\1/p'`
81echo "type timespec_sec_t $timespec_sec" >> ${OUT}
82echo "type timespec_nsec_t $timespec_nsec" >> ${OUT}
83echo $timespec | \
84  sed -e 's/^type ___timespec /type timespec /' \
85      -e 's/^type _timespec /type timespec /' \
86      -e 's/tv_sec *[a-zA-Z0-9_]*/tv_sec timespec_sec_t/' \
87      -e 's/tv_nsec *[a-zA-Z0-9_]*/tv_nsec timespec_nsec_t/' >> ${OUT}
88echo >> ${OUT}
89echo "func (ts *timespec) setNsec(ns int64) {" >> ${OUT}
90echo "	ts.tv_sec = timespec_sec_t(ns / 1e9)" >> ${OUT}
91echo "	ts.tv_nsec = timespec_nsec_t(ns % 1e9)" >> ${OUT}
92echo "}" >> ${OUT}
93echo >> ${OUT}
94
95# Define the epollevent struct.  This needs special attention because
96# the C definition uses a union and is sometimes packed.
97if grep '^const _epoll_data_offset ' ${OUT} >/dev/null 2>&1; then
98  val=`grep '^const _epoll_data_offset ' ${OUT} | sed -e 's/const _epoll_data_offset = \(.*\)$/\1/'`
99  if test "$val" = "4"; then
100      echo 'type epollevent struct { events uint32; data [8]byte }' >> ${OUT}
101  elif test "$val" = "8"; then
102      if test "$GOARCH" = "sparc64" -a "$GOOS" = "linux"; then
103          echo 'type epollevent struct { events uint32; pad [4]byte; data [8]byte; _align [0]int64 }' >> ${OUT}
104      else
105          echo 'type epollevent struct { events uint32; pad [4]byte; data [8]byte }' >> ${OUT}
106      fi
107  else
108      echo 1>&2 "unknown epoll data offset value ${val}"
109      exit 1
110  fi
111fi
112# Make sure EPOLLET is positive.
113if grep '^const _EPOLLET = [0-9]' gen-sysinfo.go > /dev/null 2>&1; then
114  echo "const _EPOLLETpos = _EPOLLET" >> ${OUT}
115else
116  echo "const _EPOLLETpos = 0x80000000" >> ${OUT}
117fi
118# Make sure EPOLLRDHUP and EPOLL_CLOEXEC are defined.
119if ! grep '^const _EPOLLRDHUP' ${OUT} >/dev/null 2>&1; then
120  echo "const _EPOLLRDHUP = 0x2000" >> ${OUT}
121fi
122if ! grep '^const _EPOLL_CLOEXEC' ${OUT} >/dev/null 2>&1; then
123  echo "const _EPOLL_CLOEXEC = 02000000" >> ${OUT}
124fi
125
126# AIX 7.1 is a 64 bits value for _FCLOEXEC (referenced by O_CLOEXEC)
127# which leads to a constant overflow when using O_CLOEXEC in some
128# go code. Issue wan not present in 6.1 (no O_CLOEXEC) and is no
129# more present in 7.2 (_FCLOEXEC is a 32 bit value).
130if test "${GOOS}" = "aix" && `oslevel | grep -q "^7.1"`; then
131    sed -e 's/const __FCLOEXEC = .*/const __FCLOEXEC = 0/' ${OUT} > ${OUT}-2
132    mv ${OUT}-2 ${OUT}
133fi
134
135# Make sure _MAP_FAILED is defined.
136if ! grep '^const _MAP_FAILED =' gen-sysinfo.go > /dev/null 2>&1; then
137  echo "const _MAP_FAILED = ^uintptr(0)" >> ${OUT}
138fi
139# Make sure _MAP_ANON is defined.
140if ! grep '^const _MAP_ANON =' gen-sysinfo.go > /dev/null 2>&1; then
141  if grep '^const _MAP_ANONYMOUS ' gen-sysinfo.go > /dev/null 2>&1; then
142    echo "const _MAP_ANON = _MAP_ANONYMOUS" >> ${OUT}
143  else
144    echo "const _MAP_ANON = 0" >> ${OUT}
145  fi
146fi
147# Make sure _MADV_DONTNEED is defined.
148if ! grep '^const _MADV_DONTNEED =' gen-sysinfo.go > /dev/null 2>&1; then
149  echo "const _MADV_DONTNEED = 0" >> ${OUT}
150fi
151# Make sure _MADV_FREE is defined.
152if ! grep '^const _MADV_FREE =' gen-sysinfo.go > /dev/null 2>&1; then
153  echo "const _MADV_FREE = 0" >> ${OUT}
154fi
155# Make sure _MADV_HUGEPAGE is defined.
156if ! grep '^const _MADV_HUGEPAGE =' gen-sysinfo.go > /dev/null 2>&1; then
157  echo "const _MADV_HUGEPAGE = 0" >> ${OUT}
158fi
159# Make sure _MADV_NOHUGEPAGE is defined.
160if ! grep '^const _MADV_NOHUGEPAGE =' gen-sysinfo.go > /dev/null 2>&1; then
161  echo "const _MADV_NOHUGEPAGE = 0" >> ${OUT}
162fi
163
164# The semt structure, for Solaris.
165grep '^type _sem_t ' gen-sysinfo.go | \
166    sed -e 's/_sem_t/semt/' >> ${OUT}
167
168# Solaris 2 needs _u?pad128_t, but its default definition in terms of long
169# double is commented by -fdump-go-spec.
170if grep "^// type _pad128_t" gen-sysinfo.go > /dev/null 2>&1; then
171  echo "type _pad128_t struct { _l [4]int32; }" >> ${OUT}
172fi
173if grep "^// type _upad128_t" gen-sysinfo.go > /dev/null 2>&1; then
174  echo "type _upad128_t struct { _l [4]uint32; }" >> ${OUT}
175fi
176
177# The Solaris 11 Update 1 _zone_net_addr_t struct.
178grep '^type _zone_net_addr_t ' gen-sysinfo.go | \
179    sed -e 's/_in6_addr/[16]byte/' \
180    >> ${OUT}
181
182# The Solaris 11.4 _flow_arp_desc_t struct.
183grep '^type _flow_arp_desc_t ' gen-sysinfo.go | \
184    sed -e 's/_in6_addr_t/[16]byte/g' \
185    >> ${OUT}
186
187# The Solaris 11.4 _flow_l3_desc_t struct.
188grep '^type _flow_l3_desc_t ' gen-sysinfo.go | \
189    sed -e 's/_in6_addr_t/[16]byte/g' \
190    >> ${OUT}
191
192# The Solaris 11.3 _mac_ipaddr_t struct.
193grep '^type _mac_ipaddr_t ' gen-sysinfo.go | \
194    sed -e 's/_in6_addr_t/[16]byte/g' \
195    >> ${OUT}
196
197# The Solaris 11.3 _mactun_info_t struct.
198grep '^type _mactun_info_t ' gen-sysinfo.go | \
199    sed -e 's/_in6_addr_t/[16]byte/g' \
200    >> ${OUT}
201
202# The Solaris port_event_t struct.
203grep '^type _port_event_t ' gen-sysinfo.go | \
204    sed -e s'/_port_event_t/portevent/' \
205    >> ${OUT}
206
207# The *BSD kevent struct.
208grep '^type _kevent ' gen-sysinfo.go | \
209    sed -e s'/_kevent/keventt/' \
210      -e 's/ udata [^;}]*/ udata *byte/' \
211    >> ${OUT}
212
213# Type 'uint128' is needed in a couple of type definitions on arm64,such
214# as _user_fpsimd_struct, _elf_fpregset_t, etc.
215if ! grep '^type uint128' ${OUT} > /dev/null 2>&1; then
216    echo "type uint128 [16]byte" >> ${OUT}
217fi
218