@@ -27,6 +27,7 @@ import (
27
27
"slices"
28
28
"strconv"
29
29
"strings"
30
+ "sync/atomic"
30
31
"unicode"
31
32
"unicode/utf8"
32
33
@@ -194,13 +195,12 @@ func (p *Package) Translate(f *File) {
194
195
var conv typeConv
195
196
conv .Init (p .PtrSize , p .IntSize )
196
197
197
- p .typedefs = map [string ]bool {}
198
- p .typedefList = nil
198
+ ft := fileTypedefs {typedefs : make (map [string ]bool )}
199
199
numTypedefs := - 1
200
- for len (p .typedefs ) > numTypedefs {
201
- numTypedefs = len (p .typedefs )
200
+ for len (ft .typedefs ) > numTypedefs {
201
+ numTypedefs = len (ft .typedefs )
202
202
// Also ask about any typedefs we've seen so far.
203
- for _ , info := range p .typedefList {
203
+ for _ , info := range ft .typedefList {
204
204
if f .Name [info .typedef ] != nil {
205
205
continue
206
206
}
@@ -213,7 +213,8 @@ func (p *Package) Translate(f *File) {
213
213
}
214
214
needType := p .guessKinds (f )
215
215
if len (needType ) > 0 {
216
- p .loadDWARF (f , & conv , needType )
216
+ d := p .loadDWARF (f , & ft , needType )
217
+ p .recordTypes (f , d , & conv )
217
218
}
218
219
219
220
// In godefs mode we're OK with the typedefs, which
@@ -522,7 +523,7 @@ func (p *Package) guessKinds(f *File) []*Name {
522
523
// loadDWARF parses the DWARF debug information generated
523
524
// by gcc to learn the details of the constants, variables, and types
524
525
// being referred to as C.xxx.
525
- func (p * Package ) loadDWARF (f * File , conv * typeConv , names []* Name ) {
526
+ func (p * Package ) loadDWARF (f * File , ft * fileTypedefs , names []* Name ) * debug {
526
527
// Extract the types from the DWARF section of an object
527
528
// from a well-formed C program. Gcc only generates DWARF info
528
529
// for symbols in the object file, so it is not enough to print the
@@ -636,13 +637,28 @@ func (p *Package) loadDWARF(f *File, conv *typeConv, names []*Name) {
636
637
fatalf ("malformed __cgo__ name: %s" , name )
637
638
}
638
639
types [i ] = t .Type
639
- p .recordTypedefs (t .Type , f.NamePos [names [i ]])
640
+ ft .recordTypedefs (t .Type , f.NamePos [names [i ]])
640
641
}
641
642
if e .Tag != dwarf .TagCompileUnit {
642
643
r .SkipChildren ()
643
644
}
644
645
}
645
646
647
+ return & debug {names , types , ints , floats , strs }
648
+ }
649
+
650
+ // debug is the data extracted by running an iteration of loadDWARF on a file.
651
+ type debug struct {
652
+ names []* Name
653
+ types []dwarf.Type
654
+ ints []int64
655
+ floats []float64
656
+ strs []string
657
+ }
658
+
659
+ func (p * Package ) recordTypes (f * File , data * debug , conv * typeConv ) {
660
+ names , types , ints , floats , strs := data .names , data .types , data .ints , data .floats , data .strs
661
+
646
662
// Record types and typedef information.
647
663
for i , n := range names {
648
664
if strings .HasSuffix (n .Go , "GetTypeID" ) && types [i ].String () == "func() CFTypeID" {
@@ -701,12 +717,17 @@ func (p *Package) loadDWARF(f *File, conv *typeConv, names []*Name) {
701
717
}
702
718
}
703
719
704
- // recordTypedefs remembers in p.typedefs all the typedefs used in dtypes and its children.
705
- func (p * Package ) recordTypedefs (dtype dwarf.Type , pos token.Pos ) {
706
- p .recordTypedefs1 (dtype , pos , map [dwarf.Type ]bool {})
720
+ type fileTypedefs struct {
721
+ typedefs map [string ]bool // type names that appear in the types of the objects we're interested in
722
+ typedefList []typedefInfo
723
+ }
724
+
725
+ // recordTypedefs remembers in ft.typedefs all the typedefs used in dtypes and its children.
726
+ func (ft * fileTypedefs ) recordTypedefs (dtype dwarf.Type , pos token.Pos ) {
727
+ ft .recordTypedefs1 (dtype , pos , map [dwarf.Type ]bool {})
707
728
}
708
729
709
- func (p * Package ) recordTypedefs1 (dtype dwarf.Type , pos token.Pos , visited map [dwarf.Type ]bool ) {
730
+ func (ft * fileTypedefs ) recordTypedefs1 (dtype dwarf.Type , pos token.Pos , visited map [dwarf.Type ]bool ) {
710
731
if dtype == nil {
711
732
return
712
733
}
@@ -720,25 +741,25 @@ func (p *Package) recordTypedefs1(dtype dwarf.Type, pos token.Pos, visited map[d
720
741
// Don't look inside builtin types. There be dragons.
721
742
return
722
743
}
723
- if ! p .typedefs [dt .Name ] {
724
- p .typedefs [dt .Name ] = true
725
- p .typedefList = append (p .typedefList , typedefInfo {dt .Name , pos })
726
- p .recordTypedefs1 (dt .Type , pos , visited )
744
+ if ! ft .typedefs [dt .Name ] {
745
+ ft .typedefs [dt .Name ] = true
746
+ ft .typedefList = append (ft .typedefList , typedefInfo {dt .Name , pos })
747
+ ft .recordTypedefs1 (dt .Type , pos , visited )
727
748
}
728
749
case * dwarf.PtrType :
729
- p .recordTypedefs1 (dt .Type , pos , visited )
750
+ ft .recordTypedefs1 (dt .Type , pos , visited )
730
751
case * dwarf.ArrayType :
731
- p .recordTypedefs1 (dt .Type , pos , visited )
752
+ ft .recordTypedefs1 (dt .Type , pos , visited )
732
753
case * dwarf.QualType :
733
- p .recordTypedefs1 (dt .Type , pos , visited )
754
+ ft .recordTypedefs1 (dt .Type , pos , visited )
734
755
case * dwarf.FuncType :
735
- p .recordTypedefs1 (dt .ReturnType , pos , visited )
756
+ ft .recordTypedefs1 (dt .ReturnType , pos , visited )
736
757
for _ , a := range dt .ParamType {
737
- p .recordTypedefs1 (a , pos , visited )
758
+ ft .recordTypedefs1 (a , pos , visited )
738
759
}
739
760
case * dwarf.StructType :
740
- for _ , f := range dt .Field {
741
- p .recordTypedefs1 (f .Type , pos , visited )
761
+ for _ , l := range dt .Field {
762
+ ft .recordTypedefs1 (l .Type , pos , visited )
742
763
}
743
764
}
744
765
}
@@ -1756,20 +1777,23 @@ func gccMachine() []string {
1756
1777
return nil
1757
1778
}
1758
1779
1780
+ var n atomic.Int64
1781
+
1759
1782
func gccTmp () string {
1760
- return * objDir + "_cgo_.o"
1783
+ c := strconv .Itoa (int (n .Add (1 )))
1784
+ return * objDir + "_cgo_" + c + ".o"
1761
1785
}
1762
1786
1763
1787
// gccCmd returns the gcc command line to use for compiling
1764
1788
// the input.
1765
- func (p * Package ) gccCmd () []string {
1789
+ func (p * Package ) gccCmd (ofile string ) []string {
1766
1790
c := append (gccBaseCmd ,
1767
- "-w" , // no warnings
1768
- "-Wno-error" , // warnings are not errors
1769
- "-o" + gccTmp (), // write object to tmp
1770
- "-gdwarf-2" , // generate DWARF v2 debugging symbols
1771
- "-c" , // do not link
1772
- "-xc" , // input language is C
1791
+ "-w" , // no warnings
1792
+ "-Wno-error" , // warnings are not errors
1793
+ "-o" + ofile , // write object to tmp
1794
+ "-gdwarf-2" , // generate DWARF v2 debugging symbols
1795
+ "-c" , // do not link
1796
+ "-xc" , // input language is C
1773
1797
)
1774
1798
if p .GccIsClang {
1775
1799
c = append (c ,
@@ -1806,7 +1830,8 @@ func (p *Package) gccCmd() []string {
1806
1830
// gccDebug runs gcc -gdwarf-2 over the C program stdin and
1807
1831
// returns the corresponding DWARF data and, if present, debug data block.
1808
1832
func (p * Package ) gccDebug (stdin []byte , nnames int ) (d * dwarf.Data , ints []int64 , floats []float64 , strs []string ) {
1809
- runGcc (stdin , p .gccCmd ())
1833
+ ofile := gccTmp ()
1834
+ runGcc (stdin , p .gccCmd (ofile ))
1810
1835
1811
1836
isDebugInts := func (s string ) bool {
1812
1837
// Some systems use leading _ to denote non-assembly symbols.
@@ -1856,11 +1881,11 @@ func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int6
1856
1881
}
1857
1882
}
1858
1883
1859
- if f , err := macho .Open (gccTmp () ); err == nil {
1884
+ if f , err := macho .Open (ofile ); err == nil {
1860
1885
defer f .Close ()
1861
1886
d , err := f .DWARF ()
1862
1887
if err != nil {
1863
- fatalf ("cannot load DWARF output from %s: %v" , gccTmp () , err )
1888
+ fatalf ("cannot load DWARF output from %s: %v" , ofile , err )
1864
1889
}
1865
1890
bo := f .ByteOrder
1866
1891
if f .Symtab != nil {
@@ -1934,11 +1959,11 @@ func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int6
1934
1959
return d , ints , floats , strs
1935
1960
}
1936
1961
1937
- if f , err := elf .Open (gccTmp () ); err == nil {
1962
+ if f , err := elf .Open (ofile ); err == nil {
1938
1963
defer f .Close ()
1939
1964
d , err := f .DWARF ()
1940
1965
if err != nil {
1941
- fatalf ("cannot load DWARF output from %s: %v" , gccTmp () , err )
1966
+ fatalf ("cannot load DWARF output from %s: %v" , ofile , err )
1942
1967
}
1943
1968
bo := f .ByteOrder
1944
1969
symtab , err := f .Symbols ()
@@ -2034,11 +2059,11 @@ func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int6
2034
2059
return d , ints , floats , strs
2035
2060
}
2036
2061
2037
- if f , err := pe .Open (gccTmp () ); err == nil {
2062
+ if f , err := pe .Open (ofile ); err == nil {
2038
2063
defer f .Close ()
2039
2064
d , err := f .DWARF ()
2040
2065
if err != nil {
2041
- fatalf ("cannot load DWARF output from %s: %v" , gccTmp () , err )
2066
+ fatalf ("cannot load DWARF output from %s: %v" , ofile , err )
2042
2067
}
2043
2068
bo := binary .LittleEndian
2044
2069
for _ , s := range f .Symbols {
@@ -2106,11 +2131,11 @@ func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int6
2106
2131
return d , ints , floats , strs
2107
2132
}
2108
2133
2109
- if f , err := xcoff .Open (gccTmp () ); err == nil {
2134
+ if f , err := xcoff .Open (ofile ); err == nil {
2110
2135
defer f .Close ()
2111
2136
d , err := f .DWARF ()
2112
2137
if err != nil {
2113
- fatalf ("cannot load DWARF output from %s: %v" , gccTmp () , err )
2138
+ fatalf ("cannot load DWARF output from %s: %v" , ofile , err )
2114
2139
}
2115
2140
bo := binary .BigEndian
2116
2141
for _ , s := range f .Symbols {
@@ -2176,7 +2201,7 @@ func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int6
2176
2201
buildStrings ()
2177
2202
return d , ints , floats , strs
2178
2203
}
2179
- fatalf ("cannot parse gcc output %s as ELF, Mach-O, PE, XCOFF object" , gccTmp () )
2204
+ fatalf ("cannot parse gcc output %s as ELF, Mach-O, PE, XCOFF object" , ofile )
2180
2205
panic ("not reached" )
2181
2206
}
2182
2207
@@ -2196,7 +2221,7 @@ func gccDefines(stdin []byte, gccOptions []string) string {
2196
2221
// gcc to fail.
2197
2222
func (p * Package ) gccErrors (stdin []byte , extraArgs ... string ) string {
2198
2223
// TODO(rsc): require failure
2199
- args := p .gccCmd ()
2224
+ args := p .gccCmd (gccTmp () )
2200
2225
2201
2226
// Optimization options can confuse the error messages; remove them.
2202
2227
nargs := make ([]string , 0 , len (args )+ len (extraArgs ))
0 commit comments