...
1
2
3
4
5 package ld
6
7 import (
8 "cmd/internal/objabi"
9 "cmd/link/internal/loader"
10 "cmd/link/internal/sym"
11 "fmt"
12 "sort"
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 func (ctxt *Link) inittasks() {
41 switch ctxt.BuildMode {
42 case BuildModeExe, BuildModePIE, BuildModeCArchive, BuildModeCShared:
43
44 ctxt.mainInittasks = ctxt.inittaskSym([]string{"main..inittask"}, "go:main.inittasks")
45 case BuildModePlugin:
46
47 ctxt.mainInittasks = ctxt.inittaskSym([]string{fmt.Sprintf("%s..inittask", objabi.PathToPrefix(*flagPluginPath))}, "go:plugin.inittasks")
48
49 ctxt.loader.SetAttrLocal(ctxt.mainInittasks, true)
50 case BuildModeShared:
51
52 var roots []string
53 for _, lib := range ctxt.Library {
54 roots = append(roots, fmt.Sprintf("%s..inittask", objabi.PathToPrefix(lib.Pkg)))
55 }
56 ctxt.mainInittasks = ctxt.inittaskSym(roots, "go:shlib.inittasks")
57
58 ctxt.loader.SetAttrLocal(ctxt.mainInittasks, true)
59 default:
60 Exitf("unhandled build mode %d", ctxt.BuildMode)
61 }
62
63
64
65 ldr := ctxt.loader
66 if ldr.Lookup("runtime.runtime_inittasks", 0) != 0 {
67 t := ctxt.inittaskSym([]string{"runtime..inittask"}, "go:runtime.inittasks")
68
69
70 sh := ldr.Lookup("runtime.runtime_inittasks", 0)
71 sb := ldr.MakeSymbolUpdater(sh)
72 sb.SetSize(0)
73 sb.SetType(sym.SNOPTRDATA)
74 sb.AddAddr(ctxt.Arch, t)
75 sb.AddUint(ctxt.Arch, uint64(ldr.SymSize(t)/int64(ctxt.Arch.PtrSize)))
76 sb.AddUint(ctxt.Arch, uint64(ldr.SymSize(t)/int64(ctxt.Arch.PtrSize)))
77 }
78 }
79
80
81
82 func (ctxt *Link) inittaskSym(rootNames []string, symName string) loader.Sym {
83 ldr := ctxt.loader
84 var roots []loader.Sym
85 for _, n := range rootNames {
86 p := ldr.Lookup(n, 0)
87 if p != 0 {
88 roots = append(roots, p)
89 }
90 }
91 if len(roots) == 0 {
92
93 return 0
94 }
95
96
97
98
99 type edge struct {
100 from, to loader.Sym
101 }
102 var edges []edge
103
104
105
106
107 var h lexHeap
108
109
110
111 m := map[loader.Sym]int{}
112
113
114
115
116
117 var q []loader.Sym
118 for _, p := range roots {
119 m[p] = 0
120 q = append(q, p)
121 }
122 for len(q) > 0 {
123 x := q[len(q)-1]
124 q = q[:len(q)-1]
125 relocs := ldr.Relocs(x)
126 n := relocs.Count()
127 ndeps := 0
128 for i := 0; i < n; i++ {
129 r := relocs.At(i)
130 if r.Type() != objabi.R_INITORDER {
131 continue
132 }
133 ndeps++
134 s := r.Sym()
135 edges = append(edges, edge{from: x, to: s})
136 if _, ok := m[s]; ok {
137 continue
138 }
139 q = append(q, s)
140 m[s] = 0
141 }
142 m[x] = ndeps
143 if ndeps == 0 {
144 h.push(ldr, x)
145 }
146 }
147
148
149 sort.Slice(edges, func(i, j int) bool {
150 return edges[i].to < edges[j].to
151 })
152
153
154 sched := ldr.MakeSymbolBuilder(symName)
155 sched.SetType(sym.SNOPTRDATA)
156 for !h.empty() {
157
158 s := h.pop(ldr)
159
160
161 if ldr.SymSize(s) > 8 {
162
163
164
165
166 sched.AddAddr(ctxt.Arch, s)
167 }
168
169
170 a := sort.Search(len(edges), func(i int) bool { return edges[i].to >= s })
171 b := sort.Search(len(edges), func(i int) bool { return edges[i].to > s })
172
173
174
175 for _, e := range edges[a:b] {
176 m[e.from]--
177 if m[e.from] == 0 {
178 h.push(ldr, e.from)
179 }
180 }
181 }
182
183 for s, n := range m {
184 if n != 0 {
185 Exitf("inittask for %s is not schedulable %d", ldr.SymName(s), n)
186 }
187 }
188 return sched.Sym()
189 }
190
View as plain text