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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package main
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"strconv"
"strings"
)
// fetchValues converts literal constants (e.g. O_APPEND) or any other C expressions
// into their respective numeric values. It does so by builting and executing a C program
// that prints values of the provided expressions.
func fetchValues(arch string, vals []string, includes []string, defines map[string]string) []string {
logf(1, "Use C compiler to fetch constant values for arch=%v", arch)
includeText := ""
for _, inc := range includes {
includeText += fmt.Sprintf("#include <%v>\n", inc)
}
definesText := ""
for k, v := range defines {
definesText += fmt.Sprintf("#ifndef %v\n#define %v %v\n#endif\n", k, k, v)
}
src := strings.Replace(fetchSrc, "[[INCLUDES]]", includeText, 1)
src = strings.Replace(src, "[[DEFAULTS]]", definesText, 1)
src = strings.Replace(src, "[[VALS]]", strings.Join(vals, ","), 1)
bin, err := ioutil.TempFile("", "")
if err != nil {
failf("failed to create temp file: %v", err)
}
bin.Close()
defer os.Remove(bin.Name())
logf(2, " Build C program into temp file %v", bin.Name())
args := []string{"-x", "c", "-", "-o", bin.Name()}
args = append(args, []string{
// This would be useful to ensure that we don't include any host headers,
// but kernel includes at least <stdarg.h>
// "-nostdinc",
"-I.",
"-D__KERNEL__",
"-DKBUILD_MODNAME=\"-\"",
"-I" + *flagLinux + "/arch/" + arch + "/include",
"-I" + *flagLinuxBld + "/arch/" + arch + "/include/generated/uapi",
"-I" + *flagLinuxBld + "/arch/" + arch + "/include/generated",
"-I" + *flagLinuxBld + "/include",
"-I" + *flagLinux + "/include",
"-I" + *flagLinux + "/arch/" + arch + "/include/uapi",
"-I" + *flagLinuxBld + "/arch/" + arch + "/include/generated/uapi",
"-I" + *flagLinux + "/include/uapi",
"-I" + *flagLinuxBld + "/include/generated/uapi",
"-I" + *flagLinux,
"-include", *flagLinux + "/include/linux/kconfig.h",
}...)
logf(4, " Source code:\n%v", src)
logf(2, " Execute gcc with: %v", args)
cmd := exec.Command("gcc", args...)
cmd.Stdin = strings.NewReader(src)
out, err := cmd.CombinedOutput()
if err != nil {
failf("failed to run gcc: %v\n%v", err, string(out))
}
out, err = exec.Command(bin.Name()).CombinedOutput()
if err != nil {
failf("failed to flags binary: %v\n%v", err, string(out))
}
flagVals := strings.Split(string(out), " ")
if len(flagVals) != len(vals) {
failf("fetched wrong number of values")
}
for _, v := range flagVals {
_, err := strconv.ParseUint(v, 10, 64)
if err != nil {
failf("failed to parse value: %v (%v)", err, v)
}
}
return flagVals
}
var fetchSrc = `
[[INCLUDES]]
[[DEFAULTS]]
int printf(const char *format, ...);
unsigned long phys_base;
#ifndef __phys_addr
unsigned long __phys_addr(unsigned long addr) { return 0; }
#endif
int main() {
int i;
unsigned long vals[] = {[[VALS]]};
for (i = 0; i < sizeof(vals)/sizeof(vals[0]); i++) {
if (i != 0)
printf(" ");
printf("%lu", vals[i]);
}
return 0;
}
`
|