@@ -119,9 +119,18 @@ type Loader struct {
119
119
Reachparent []Sym
120
120
121
121
relocBatch []sym.Reloc // for bulk allocation of relocations
122
+
123
+ flags uint32
124
+
125
+ strictDupMsgs int // number of strict-dup warning/errors, when FlagStrictDups is enabled
122
126
}
123
127
124
- func NewLoader () * Loader {
128
+ const (
129
+ // Loader.flags
130
+ FlagStrictDups = 1 << iota
131
+ )
132
+
133
+ func NewLoader (flags uint32 ) * Loader {
125
134
nbuiltin := goobj2 .NBuiltin ()
126
135
return & Loader {
127
136
start : make (map [* oReader ]Sym ),
@@ -132,6 +141,7 @@ func NewLoader() *Loader {
132
141
itablink : make (map [Sym ]struct {}),
133
142
extStaticSyms : make (map [nameVer ]Sym ),
134
143
builtinSyms : make ([]Sym , nbuiltin ),
144
+ flags : flags ,
135
145
}
136
146
}
137
147
@@ -170,6 +180,9 @@ func (l *Loader) AddSym(name string, ver int, i Sym, r *oReader, dupok bool, typ
170
180
}
171
181
if oldi , ok := l.symsByName [ver ][name ]; ok {
172
182
if dupok {
183
+ if l .flags & FlagStrictDups != 0 {
184
+ l .checkdup (name , i , r , oldi )
185
+ }
173
186
return false
174
187
}
175
188
oldr , li := l .toLocal (oldi )
@@ -366,6 +379,42 @@ func (l *Loader) IsDup(i Sym) bool {
366
379
return l.symsByName [ver ][name ] != i
367
380
}
368
381
382
+ // Check that duplicate symbols have same contents.
383
+ func (l * Loader ) checkdup (name string , i Sym , r * oReader , dup Sym ) {
384
+ li := int (i - l .startIndex (r ))
385
+ p := r .Data (li )
386
+ if strings .HasPrefix (name , "go.info." ) {
387
+ p , _ = patchDWARFName1 (p , r )
388
+ }
389
+ rdup , ldup := l .toLocal (dup )
390
+ pdup := rdup .Data (ldup )
391
+ if strings .HasPrefix (name , "go.info." ) {
392
+ pdup , _ = patchDWARFName1 (pdup , rdup )
393
+ }
394
+ if bytes .Equal (p , pdup ) {
395
+ return
396
+ }
397
+ reason := "same length but different contents"
398
+ if len (p ) != len (pdup ) {
399
+ reason = fmt .Sprintf ("new length %d != old length %d" , len (p ), len (pdup ))
400
+ }
401
+ fmt .Fprintf (os .Stderr , "cmd/link: while reading object for '%v': duplicate symbol '%s', previous def at '%v', with mismatched payload: %s\n " , r .unit .Lib , name , rdup .unit .Lib , reason )
402
+
403
+ // For the moment, whitelist DWARF subprogram DIEs for
404
+ // auto-generated wrapper functions. What seems to happen
405
+ // here is that we get different line numbers on formal
406
+ // params; I am guessing that the pos is being inherited
407
+ // from the spot where the wrapper is needed.
408
+ whitelist := strings .HasPrefix (name , "go.info.go.interface" ) ||
409
+ strings .HasPrefix (name , "go.info.go.builtin" ) ||
410
+ strings .HasPrefix (name , "go.debuglines" )
411
+ if ! whitelist {
412
+ l .strictDupMsgs ++
413
+ }
414
+ }
415
+
416
+ func (l * Loader ) NStrictDupMsgs () int { return l .strictDupMsgs }
417
+
369
418
// Number of total symbols.
370
419
func (l * Loader ) NSym () int {
371
420
return int (l .max + 1 )
@@ -1194,24 +1243,30 @@ func loadObjFull(l *Loader, r *oReader) {
1194
1243
1195
1244
var emptyPkg = []byte (`"".` )
1196
1245
1197
- func patchDWARFName ( s * sym. Symbol , r * oReader ) {
1246
+ func patchDWARFName1 ( p [] byte , r * oReader ) ([] byte , int ) {
1198
1247
// This is kind of ugly. Really the package name should not
1199
1248
// even be included here.
1200
- if s . Size < 1 || s . P [0 ] != dwarf .DW_ABRV_FUNCTION {
1201
- return
1249
+ if len ( p ) < 1 || p [0 ] != dwarf .DW_ABRV_FUNCTION {
1250
+ return p , - 1
1202
1251
}
1203
- e := bytes .IndexByte (s . P , 0 )
1252
+ e := bytes .IndexByte (p , 0 )
1204
1253
if e == - 1 {
1205
- return
1254
+ return p , - 1
1206
1255
}
1207
- p := bytes .Index (s .P [:e ], emptyPkg )
1208
- if p == - 1 {
1209
- return
1256
+ if ! bytes .Contains (p [:e ], emptyPkg ) {
1257
+ return p , - 1
1210
1258
}
1211
1259
pkgprefix := []byte (r .pkgprefix )
1212
- patched := bytes .Replace (s .P [:e ], emptyPkg , pkgprefix , - 1 )
1260
+ patched := bytes .Replace (p [:e ], emptyPkg , pkgprefix , - 1 )
1261
+ return append (patched , p [e :]... ), e
1262
+ }
1213
1263
1214
- s .P = append (patched , s .P [e :]... )
1264
+ func patchDWARFName (s * sym.Symbol , r * oReader ) {
1265
+ patched , e := patchDWARFName1 (s .P , r )
1266
+ if e == - 1 {
1267
+ return
1268
+ }
1269
+ s .P = patched
1215
1270
s .Attr .Set (sym .AttrReadOnly , false )
1216
1271
delta := int64 (len (s .P )) - s .Size
1217
1272
s .Size = int64 (len (s .P ))
0 commit comments