@@ -7,6 +7,8 @@ package cshared_test
7
7
import (
8
8
"bytes"
9
9
"debug/elf"
10
+ "debug/pe"
11
+ "encoding/binary"
10
12
"flag"
11
13
"fmt"
12
14
"io/ioutil"
@@ -355,6 +357,100 @@ func TestExportedSymbols(t *testing.T) {
355
357
}
356
358
}
357
359
360
+ func checkNumberOfExportedFunctionsWindows (t * testing.T , exportAllSymbols bool ) {
361
+ const prog = `
362
+ package main
363
+
364
+ import "C"
365
+
366
+ //export GoFunc
367
+ func GoFunc() {
368
+ println(42)
369
+ }
370
+
371
+ //export GoFunc2
372
+ func GoFunc2() {
373
+ println(24)
374
+ }
375
+
376
+ func main() {
377
+ }
378
+ `
379
+
380
+ tmpdir := t .TempDir ()
381
+
382
+ srcfile := filepath .Join (tmpdir , "test.go" )
383
+ objfile := filepath .Join (tmpdir , "test.dll" )
384
+ if err := ioutil .WriteFile (srcfile , []byte (prog ), 0666 ); err != nil {
385
+ t .Fatal (err )
386
+ }
387
+ argv := []string {"build" , "-buildmode=c-shared" }
388
+ if exportAllSymbols {
389
+ argv = append (argv , "-ldflags" , "-extldflags=-Wl,--export-all-symbols" )
390
+ }
391
+ argv = append (argv , "-o" , objfile , srcfile )
392
+ out , err := exec .Command ("go" , argv ... ).CombinedOutput ()
393
+ if err != nil {
394
+ t .Fatalf ("build failure: %s\n %s\n " , err , string (out ))
395
+ }
396
+
397
+ f , err := pe .Open (objfile )
398
+ if err != nil {
399
+ t .Fatalf ("pe.Open failed: %v" , err )
400
+ }
401
+ defer f .Close ()
402
+ section := f .Section (".edata" )
403
+ if section == nil {
404
+ t .Error (".edata section is not present" )
405
+ }
406
+
407
+ // TODO: deduplicate this struct from cmd/link/internal/ld/pe.go
408
+ type IMAGE_EXPORT_DIRECTORY struct {
409
+ _ [2 ]uint32
410
+ _ [2 ]uint16
411
+ _ [2 ]uint32
412
+ NumberOfFunctions uint32
413
+ NumberOfNames uint32
414
+ _ [3 ]uint32
415
+ }
416
+ var e IMAGE_EXPORT_DIRECTORY
417
+ if err := binary .Read (section .Open (), binary .LittleEndian , & e ); err != nil {
418
+ t .Fatalf ("binary.Read failed: %v" , err )
419
+ }
420
+
421
+ expectedNumber := uint32 (2 )
422
+
423
+ if exportAllSymbols {
424
+ if e .NumberOfFunctions <= expectedNumber {
425
+ t .Fatalf ("missing exported functions: %v" , e .NumberOfFunctions )
426
+ }
427
+ if e .NumberOfNames <= expectedNumber {
428
+ t .Fatalf ("missing exported names: %v" , e .NumberOfNames )
429
+ }
430
+ } else {
431
+ if e .NumberOfFunctions != expectedNumber {
432
+ t .Fatalf ("too many exported functions: %v" , e .NumberOfFunctions )
433
+ }
434
+ if e .NumberOfNames != expectedNumber {
435
+ t .Fatalf ("too many exported names: %v" , e .NumberOfNames )
436
+ }
437
+ }
438
+ }
439
+
440
+ func TestNumberOfExportedFunctions (t * testing.T ) {
441
+ if GOOS != "windows" {
442
+ t .Skip ("skipping windows only test" )
443
+ }
444
+ t .Parallel ()
445
+
446
+ t .Run ("OnlyExported" , func (t * testing.T ) {
447
+ checkNumberOfExportedFunctionsWindows (t , false )
448
+ })
449
+ t .Run ("All" , func (t * testing.T ) {
450
+ checkNumberOfExportedFunctionsWindows (t , true )
451
+ })
452
+ }
453
+
358
454
// test1: shared library can be dynamically loaded and exported symbols are accessible.
359
455
func TestExportedSymbolsWithDynamicLoad (t * testing.T ) {
360
456
t .Parallel ()
0 commit comments