aboutsummaryrefslogtreecommitdiff
path: root/libgo/mklinknames.awk
blob: 71cb3be79669f240e00b5745132b3be456e59a41 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# Copyright 2020 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.

# This AWK script reads a Go file with special //extern-sysinfo
# comments annotating functions which should be linked to libc
# functions. It generates a Go file containing the appropriate
# //go:linkname directives.
#
# For each annotated function, the script searches gen-sysinfo.go
# to see if a different assembly name is known for the function.
# For example, on NetBSD, the timegm symbol is renamed to
# __timegm50 by an __asm__ annotation on its declaration in time.h.

BEGIN {
    print "// Code generated by mklinknames.awk. DO NOT EDIT."
    print ""
    print "package", package
    print ""
    print "import _ \"unsafe\""
    print ""
}

/^\/\/extern-sysinfo/ {
    cfnname = $2
    getline
    if ($1 != "func") {
	printf("mklinknames.awk: error: %s:%d: unattached extern-sysinfo directive\n", FILENAME, FNR) | "cat 1>&2"
	exit 1
    }
    split($2, a, "(")
    gofnname = a[1]
    def = sprintf("grep '^func _%s[ (]' gen-sysinfo.go", cfnname)
    # def looks like one of the following:
    #     func _timegm (*_tm) int64 __asm__("__timegm50")
    #     func _timegm (*_tm) int64 __asm__("*__timegm50")
    # The goal is to extract "__timegm50".
    if ((def | getline fndef) > 0 && match(fndef, "__asm__\\(\"\\*?")) {
	asmname = substr(fndef, RSTART + RLENGTH)
	asmname = substr(asmname, 0, length(asmname) - 2)
	printf("//go:linkname %s %s\n", gofnname, asmname)
    } else {
	# Assume the asm name is the same as the declared C name.
	printf("//go:linkname %s %s\n", gofnname, cfnname)
    }
}