@@ -173,14 +173,29 @@ func makeUpdater(l *loader.Loader, bld *loader.SymbolBuilder, s loader.Sym) *loa
173173 return bld
174174}
175175
176+ // peLoaderState holds various bits of useful state information needed
177+ // while loading a PE object file.
178+ type peLoaderState struct {
179+ l * loader.Loader
180+ arch * sys.Arch
181+ f * pe.File
182+ sectsyms map [* pe.Section ]loader.Sym
183+ sectdata map [* pe.Section ][]byte
184+ localSymVersion int
185+ }
186+
176187// Load loads the PE file pn from input.
177188// Symbols are written into syms, and a slice of the text symbols is returned.
178189// If an .rsrc section or set of .rsrc$xx sections is found, its symbols are
179190// returned as rsrc.
180191func Load (l * loader.Loader , arch * sys.Arch , localSymVersion int , input * bio.Reader , pkg string , length int64 , pn string ) (textp []loader.Sym , rsrc []loader.Sym , err error ) {
181- lookup := l .LookupOrCreateCgoExport
182- sectsyms := make (map [* pe.Section ]loader.Sym )
183- sectdata := make (map [* pe.Section ][]byte )
192+ state := & peLoaderState {
193+ l : l ,
194+ arch : arch ,
195+ sectsyms : make (map [* pe.Section ]loader.Sym ),
196+ sectdata : make (map [* pe.Section ][]byte ),
197+ localSymVersion : localSymVersion ,
198+ }
184199
185200 // Some input files are archives containing multiple of
186201 // object files, and pe.NewFile seeks to the start of
@@ -194,6 +209,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read
194209 return nil , nil , err
195210 }
196211 defer f .Close ()
212+ state .f = f
197213
198214 // TODO return error if found .cormeta
199215
@@ -210,7 +226,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read
210226 }
211227
212228 name := fmt .Sprintf ("%s(%s)" , pkg , sect .Name )
213- s := lookup (name , localSymVersion )
229+ s := state . l . LookupOrCreateCgoExport (name , localSymVersion )
214230 bld := l .MakeSymbolUpdater (s )
215231
216232 switch sect .Characteristics & (IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE ) {
@@ -235,19 +251,19 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read
235251 if err != nil {
236252 return nil , nil , err
237253 }
238- sectdata [sect ] = data
254+ state . sectdata [sect ] = data
239255 bld .SetData (data )
240256 }
241257 bld .SetSize (int64 (sect .Size ))
242- sectsyms [sect ] = s
258+ state . sectsyms [sect ] = s
243259 if sect .Name == ".rsrc" || strings .HasPrefix (sect .Name , ".rsrc$" ) {
244260 rsrc = append (rsrc , s )
245261 }
246262 }
247263
248264 // load relocations
249265 for _ , rsect := range f .Sections {
250- if _ , found := sectsyms [rsect ]; ! found {
266+ if _ , found := state . sectsyms [rsect ]; ! found {
251267 continue
252268 }
253269 if rsect .NumberOfRelocations == 0 {
@@ -263,13 +279,13 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read
263279 }
264280
265281 splitResources := strings .HasPrefix (rsect .Name , ".rsrc$" )
266- sb := l .MakeSymbolUpdater (sectsyms [rsect ])
282+ sb := l .MakeSymbolUpdater (state . sectsyms [rsect ])
267283 for j , r := range rsect .Relocs {
268284 if int (r .SymbolTableIndex ) >= len (f .COFFSymbols ) {
269285 return nil , nil , fmt .Errorf ("relocation number %d symbol index idx=%d cannot be large then number of symbols %d" , j , r .SymbolTableIndex , len (f .COFFSymbols ))
270286 }
271287 pesym := & f .COFFSymbols [r .SymbolTableIndex ]
272- _ , gosym , err := readpesym (l , arch , lookup , f , pesym , sectsyms , localSymVersion )
288+ _ , gosym , err := state . readpesym (pesym )
273289 if err != nil {
274290 return nil , nil , err
275291 }
@@ -292,60 +308,60 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read
292308 case sys .I386 , sys .AMD64 :
293309 switch r .Type {
294310 default :
295- return nil , nil , fmt .Errorf ("%s: %v: unknown relocation type %v" , pn , sectsyms [rsect ], r .Type )
311+ return nil , nil , fmt .Errorf ("%s: %v: unknown relocation type %v" , pn , state . sectsyms [rsect ], r .Type )
296312
297313 case IMAGE_REL_I386_REL32 , IMAGE_REL_AMD64_REL32 ,
298314 IMAGE_REL_AMD64_ADDR32 , // R_X86_64_PC32
299315 IMAGE_REL_AMD64_ADDR32NB :
300316 rType = objabi .R_PCREL
301317
302- rAdd = int64 (int32 (binary .LittleEndian .Uint32 (sectdata [rsect ][rOff :])))
318+ rAdd = int64 (int32 (binary .LittleEndian .Uint32 (state . sectdata [rsect ][rOff :])))
303319
304320 case IMAGE_REL_I386_DIR32NB , IMAGE_REL_I386_DIR32 :
305321 rType = objabi .R_ADDR
306322
307323 // load addend from image
308- rAdd = int64 (int32 (binary .LittleEndian .Uint32 (sectdata [rsect ][rOff :])))
324+ rAdd = int64 (int32 (binary .LittleEndian .Uint32 (state . sectdata [rsect ][rOff :])))
309325
310326 case IMAGE_REL_AMD64_ADDR64 : // R_X86_64_64
311327 rSize = 8
312328
313329 rType = objabi .R_ADDR
314330
315331 // load addend from image
316- rAdd = int64 (binary .LittleEndian .Uint64 (sectdata [rsect ][rOff :]))
332+ rAdd = int64 (binary .LittleEndian .Uint64 (state . sectdata [rsect ][rOff :]))
317333 }
318334
319335 case sys .ARM :
320336 switch r .Type {
321337 default :
322- return nil , nil , fmt .Errorf ("%s: %v: unknown ARM relocation type %v" , pn , sectsyms [rsect ], r .Type )
338+ return nil , nil , fmt .Errorf ("%s: %v: unknown ARM relocation type %v" , pn , state . sectsyms [rsect ], r .Type )
323339
324340 case IMAGE_REL_ARM_SECREL :
325341 rType = objabi .R_PCREL
326342
327- rAdd = int64 (int32 (binary .LittleEndian .Uint32 (sectdata [rsect ][rOff :])))
343+ rAdd = int64 (int32 (binary .LittleEndian .Uint32 (state . sectdata [rsect ][rOff :])))
328344
329345 case IMAGE_REL_ARM_ADDR32 , IMAGE_REL_ARM_ADDR32NB :
330346 rType = objabi .R_ADDR
331347
332- rAdd = int64 (int32 (binary .LittleEndian .Uint32 (sectdata [rsect ][rOff :])))
348+ rAdd = int64 (int32 (binary .LittleEndian .Uint32 (state . sectdata [rsect ][rOff :])))
333349
334350 case IMAGE_REL_ARM_BRANCH24 :
335351 rType = objabi .R_CALLARM
336352
337- rAdd = int64 (int32 (binary .LittleEndian .Uint32 (sectdata [rsect ][rOff :])))
353+ rAdd = int64 (int32 (binary .LittleEndian .Uint32 (state . sectdata [rsect ][rOff :])))
338354 }
339355
340356 case sys .ARM64 :
341357 switch r .Type {
342358 default :
343- return nil , nil , fmt .Errorf ("%s: %v: unknown ARM64 relocation type %v" , pn , sectsyms [rsect ], r .Type )
359+ return nil , nil , fmt .Errorf ("%s: %v: unknown ARM64 relocation type %v" , pn , state . sectsyms [rsect ], r .Type )
344360
345361 case IMAGE_REL_ARM64_ADDR32 , IMAGE_REL_ARM64_ADDR32NB :
346362 rType = objabi .R_ADDR
347363
348- rAdd = int64 (int32 (binary .LittleEndian .Uint32 (sectdata [rsect ][rOff :])))
364+ rAdd = int64 (int32 (binary .LittleEndian .Uint32 (state . sectdata [rsect ][rOff :])))
349365 }
350366 }
351367
@@ -406,12 +422,12 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read
406422 var sect * pe.Section
407423 if pesym .SectionNumber > 0 {
408424 sect = f .Sections [pesym .SectionNumber - 1 ]
409- if _ , found := sectsyms [sect ]; ! found {
425+ if _ , found := state . sectsyms [sect ]; ! found {
410426 continue
411427 }
412428 }
413429
414- bld , s , err := readpesym (l , arch , lookup , f , pesym , sectsyms , localSymVersion )
430+ bld , s , err := state . readpesym (pesym )
415431 if err != nil {
416432 return nil , nil , err
417433 }
@@ -430,7 +446,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read
430446 continue
431447 } else if pesym .SectionNumber > 0 && int (pesym .SectionNumber ) <= len (f .Sections ) {
432448 sect = f .Sections [pesym .SectionNumber - 1 ]
433- if _ , found := sectsyms [sect ]; ! found {
449+ if _ , found := state . sectsyms [sect ]; ! found {
434450 return nil , nil , fmt .Errorf ("%s: %v: missing sect.sym" , pn , s )
435451 }
436452 } else {
@@ -446,12 +462,12 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read
446462 continue
447463 }
448464 outerName := l .SymName (l .OuterSym (s ))
449- sectName := l .SymName (sectsyms [sect ])
465+ sectName := l .SymName (state . sectsyms [sect ])
450466 return nil , nil , fmt .Errorf ("%s: duplicate symbol reference: %s in both %s and %s" , pn , l .SymName (s ), outerName , sectName )
451467 }
452468
453469 bld = makeUpdater (l , bld , s )
454- sectsym := sectsyms [sect ]
470+ sectsym := state . sectsyms [sect ]
455471 bld .SetType (l .SymType (sectsym ))
456472 l .AddInteriorSym (sectsym , s )
457473 bld .SetValue (int64 (pesym .Value ))
@@ -467,7 +483,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read
467483 // Sort outer lists by address, adding to textp.
468484 // This keeps textp in increasing address order.
469485 for _ , sect := range f .Sections {
470- s := sectsyms [sect ]
486+ s := state . sectsyms [sect ]
471487 if s == 0 {
472488 continue
473489 }
@@ -490,17 +506,17 @@ func issect(s *pe.COFFSymbol) bool {
490506 return s .StorageClass == IMAGE_SYM_CLASS_STATIC && s .Type == 0 && s .Name [0 ] == '.'
491507}
492508
493- func readpesym ( l * loader. Loader , arch * sys. Arch , lookup func ( string , int ) loader. Sym , f * pe. File , pesym * pe.COFFSymbol , sectsyms map [ * pe. Section ]loader. Sym , localSymVersion int ) (* loader.SymbolBuilder , loader.Sym , error ) {
494- symname , err := pesym .FullName (f .StringTable )
509+ func ( state * peLoaderState ) readpesym ( pesym * pe.COFFSymbol ) (* loader.SymbolBuilder , loader.Sym , error ) {
510+ symname , err := pesym .FullName (state . f .StringTable )
495511 if err != nil {
496512 return nil , 0 , err
497513 }
498514 var name string
499515 if issect (pesym ) {
500- name = l .SymName (sectsyms [f .Sections [pesym .SectionNumber - 1 ]])
516+ name = state . l .SymName (state . sectsyms [state . f .Sections [pesym .SectionNumber - 1 ]])
501517 } else {
502518 name = symname
503- switch arch .Family {
519+ switch state . arch .Family {
504520 case sys .AMD64 :
505521 if name == "__imp___acrt_iob_func" {
506522 // Do not rename __imp___acrt_iob_func into __acrt_iob_func,
@@ -537,24 +553,24 @@ func readpesym(l *loader.Loader, arch *sys.Arch, lookup func(string, int) loader
537553 case IMAGE_SYM_DTYPE_FUNCTION , IMAGE_SYM_DTYPE_NULL :
538554 switch pesym .StorageClass {
539555 case IMAGE_SYM_CLASS_EXTERNAL : //global
540- s = lookup (name , 0 )
556+ s = state . l . LookupOrCreateCgoExport (name , 0 )
541557
542558 case IMAGE_SYM_CLASS_NULL , IMAGE_SYM_CLASS_STATIC , IMAGE_SYM_CLASS_LABEL :
543- s = lookup (name , localSymVersion )
544- bld = makeUpdater (l , bld , s )
559+ s = state . l . LookupOrCreateCgoExport (name , state . localSymVersion )
560+ bld = makeUpdater (state . l , bld , s )
545561 bld .SetDuplicateOK (true )
546562
547563 default :
548564 return nil , 0 , fmt .Errorf ("%s: invalid symbol binding %d" , symname , pesym .StorageClass )
549565 }
550566 }
551567
552- if s != 0 && l .SymType (s ) == 0 && (pesym .StorageClass != IMAGE_SYM_CLASS_STATIC || pesym .Value != 0 ) {
553- bld = makeUpdater (l , bld , s )
568+ if s != 0 && state . l .SymType (s ) == 0 && (pesym .StorageClass != IMAGE_SYM_CLASS_STATIC || pesym .Value != 0 ) {
569+ bld = makeUpdater (state . l , bld , s )
554570 bld .SetType (sym .SXREF )
555571 }
556572 if strings .HasPrefix (symname , "__imp_" ) {
557- bld = makeUpdater (l , bld , s )
573+ bld = makeUpdater (state . l , bld , s )
558574 bld .SetGot (- 2 ) // flag for __imp_
559575 }
560576
0 commit comments