mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/cgo: support floating point #define macros
Current code doesn't support floating point #define macros. This CL compiles floats to a object file and retrive values from it. That approach is the same work as we've already done for integers. Updates #18720 Change-Id: I88b7ab174d0f73bda975cf90c5aeb797961fe034 Reviewed-on: https://go-review.googlesource.com/35511 Reviewed-by: Ian Lance Taylor <iant@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
735fe51a4b
commit
89ff0b1b6b
4 changed files with 163 additions and 65 deletions
|
|
@ -74,18 +74,15 @@ func testNaming(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This would be nice, but it has never worked.
|
if c := C.myfloat_def; c != 1.5 {
|
||||||
/*
|
t.Errorf("C.myint_def = %v, want 1.5", c)
|
||||||
if c := C.myfloat_def; c != 1.5 {
|
}
|
||||||
t.Errorf("C.myint_def = %v, want 1.5", c)
|
{
|
||||||
}
|
const c = C.myfloat_def
|
||||||
{
|
if c != 1.5 {
|
||||||
const c = C.myfloat_def
|
|
||||||
if c != 1.5 {
|
|
||||||
t.Errorf("C.myint as const = %v, want 1.5", c)
|
t.Errorf("C.myint as const = %v, want 1.5", c)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
*/
|
}
|
||||||
|
|
||||||
if s := C.mystring_def; s != "hello" {
|
if s := C.mystring_def; s != "hello" {
|
||||||
t.Errorf("C.mystring_def = %q, want %q", s, "hello")
|
t.Errorf("C.mystring_def = %q, want %q", s, "hello")
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/parser"
|
"go/parser"
|
||||||
"go/token"
|
"go/token"
|
||||||
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -241,26 +242,26 @@ func (p *Package) guessKinds(f *File) []*Name {
|
||||||
// If we've already found this name as a #define
|
// If we've already found this name as a #define
|
||||||
// and we can translate it as a constant value, do so.
|
// and we can translate it as a constant value, do so.
|
||||||
if n.Define != "" {
|
if n.Define != "" {
|
||||||
isConst := false
|
if i, err := strconv.ParseInt(n.Define, 0, 64); err == nil {
|
||||||
if _, err := strconv.Atoi(n.Define); err == nil {
|
n.Kind = "iconst"
|
||||||
isConst = true
|
|
||||||
} else if n.Define[0] == '"' || n.Define[0] == '\'' {
|
|
||||||
if _, err := parser.ParseExpr(n.Define); err == nil {
|
|
||||||
isConst = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if isConst {
|
|
||||||
n.Kind = "const"
|
|
||||||
// Turn decimal into hex, just for consistency
|
// Turn decimal into hex, just for consistency
|
||||||
// with enum-derived constants. Otherwise
|
// with enum-derived constants. Otherwise
|
||||||
// in the cgo -godefs output half the constants
|
// in the cgo -godefs output half the constants
|
||||||
// are in hex and half are in whatever the #define used.
|
// are in hex and half are in whatever the #define used.
|
||||||
i, err := strconv.ParseInt(n.Define, 0, 64)
|
n.Const = fmt.Sprintf("%#x", i)
|
||||||
if err == nil {
|
} else if n.Define[0] == '\'' {
|
||||||
n.Const = fmt.Sprintf("%#x", i)
|
if _, err := parser.ParseExpr(n.Define); err == nil {
|
||||||
} else {
|
n.Kind = "iconst"
|
||||||
n.Const = n.Define
|
n.Const = n.Define
|
||||||
}
|
}
|
||||||
|
} else if n.Define[0] == '"' {
|
||||||
|
if _, err := parser.ParseExpr(n.Define); err == nil {
|
||||||
|
n.Kind = "sconst"
|
||||||
|
n.Const = n.Define
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if n.IsConst() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -298,14 +299,18 @@ func (p *Package) guessKinds(f *File) []*Name {
|
||||||
// void __cgo_f_xxx_1(void) { __typeof__(name) *__cgo_undefined__; }
|
// void __cgo_f_xxx_1(void) { __typeof__(name) *__cgo_undefined__; }
|
||||||
// #line xxx "not-type"
|
// #line xxx "not-type"
|
||||||
// void __cgo_f_xxx_2(void) { name *__cgo_undefined__; }
|
// void __cgo_f_xxx_2(void) { name *__cgo_undefined__; }
|
||||||
// #line xxx "not-const"
|
// #line xxx "not-int-const"
|
||||||
// void __cgo_f_xxx_3(void) { enum { __cgo_undefined__ = (name)*1 }; }
|
// void __cgo_f_xxx_3(void) { enum { __cgo_undefined__ = (name)*1 }; }
|
||||||
|
// #line xxx "not-num-const"
|
||||||
|
// void __cgo_f_xxx_4(void) { static const double x = (name); }
|
||||||
|
// #line xxx "not-str-lit"
|
||||||
|
// void __cgo_f_xxx_5(void) { static const char x[] = (name); }
|
||||||
//
|
//
|
||||||
// If we see an error at not-declared:xxx, the corresponding name is not declared.
|
// If we see an error at not-declared:xxx, the corresponding name is not declared.
|
||||||
// If we see an error at not-type:xxx, the corresponding name is a type.
|
// If we see an error at not-type:xxx, the corresponding name is a type.
|
||||||
// If we see an error at not-const:xxx, the corresponding name is not an integer constant.
|
// If we see an error at not-int-const:xxx, the corresponding name is not an integer constant.
|
||||||
// If we see no errors, we assume the name is an expression but not a constant
|
// If we see an error at not-num-const:xxx, the corresponding name is not a number constant.
|
||||||
// (so a variable or a function).
|
// If we see an error at not-str-lit:xxx, the corresponding name is not a string literal.
|
||||||
//
|
//
|
||||||
// The specific input forms are chosen so that they are valid C syntax regardless of
|
// The specific input forms are chosen so that they are valid C syntax regardless of
|
||||||
// whether name denotes a type or an expression.
|
// whether name denotes a type or an expression.
|
||||||
|
|
@ -319,8 +324,14 @@ func (p *Package) guessKinds(f *File) []*Name {
|
||||||
"void __cgo_f_%d_1(void) { __typeof__(%s) *__cgo_undefined__; }\n"+
|
"void __cgo_f_%d_1(void) { __typeof__(%s) *__cgo_undefined__; }\n"+
|
||||||
"#line %d \"not-type\"\n"+
|
"#line %d \"not-type\"\n"+
|
||||||
"void __cgo_f_%d_2(void) { %s *__cgo_undefined__; }\n"+
|
"void __cgo_f_%d_2(void) { %s *__cgo_undefined__; }\n"+
|
||||||
"#line %d \"not-const\"\n"+
|
"#line %d \"not-int-const\"\n"+
|
||||||
"void __cgo_f_%d_3(void) { enum { __cgo__undefined__ = (%s)*1 }; }\n",
|
"void __cgo_f_%d_3(void) { enum { __cgo_undefined__ = (%s)*1 }; }\n"+
|
||||||
|
"#line %d \"not-num-const\"\n"+
|
||||||
|
"void __cgo_f_%d_4(void) { static const double x = (%s); }\n"+
|
||||||
|
"#line %d \"not-str-lit\"\n"+
|
||||||
|
"void __cgo_f_%d_5(void) { static const char s[] = (%s); }\n",
|
||||||
|
i+1, i+1, n.C,
|
||||||
|
i+1, i+1, n.C,
|
||||||
i+1, i+1, n.C,
|
i+1, i+1, n.C,
|
||||||
i+1, i+1, n.C,
|
i+1, i+1, n.C,
|
||||||
i+1, i+1, n.C)
|
i+1, i+1, n.C)
|
||||||
|
|
@ -337,7 +348,9 @@ func (p *Package) guessKinds(f *File) []*Name {
|
||||||
sniff := make([]int, len(names))
|
sniff := make([]int, len(names))
|
||||||
const (
|
const (
|
||||||
notType = 1 << iota
|
notType = 1 << iota
|
||||||
notConst
|
notIntConst
|
||||||
|
notNumConst
|
||||||
|
notStrLiteral
|
||||||
notDeclared
|
notDeclared
|
||||||
)
|
)
|
||||||
for _, line := range strings.Split(stderr, "\n") {
|
for _, line := range strings.Split(stderr, "\n") {
|
||||||
|
|
@ -376,8 +389,12 @@ func (p *Package) guessKinds(f *File) []*Name {
|
||||||
sniff[i] |= notDeclared
|
sniff[i] |= notDeclared
|
||||||
case "not-type":
|
case "not-type":
|
||||||
sniff[i] |= notType
|
sniff[i] |= notType
|
||||||
case "not-const":
|
case "not-int-const":
|
||||||
sniff[i] |= notConst
|
sniff[i] |= notIntConst
|
||||||
|
case "not-num-const":
|
||||||
|
sniff[i] |= notNumConst
|
||||||
|
case "not-str-lit":
|
||||||
|
sniff[i] |= notStrLiteral
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -389,11 +406,15 @@ func (p *Package) guessKinds(f *File) []*Name {
|
||||||
switch sniff[i] {
|
switch sniff[i] {
|
||||||
default:
|
default:
|
||||||
error_(token.NoPos, "could not determine kind of name for C.%s", fixGo(n.Go))
|
error_(token.NoPos, "could not determine kind of name for C.%s", fixGo(n.Go))
|
||||||
case notType:
|
case notStrLiteral | notType:
|
||||||
n.Kind = "const"
|
n.Kind = "iconst"
|
||||||
case notConst:
|
case notIntConst | notStrLiteral | notType:
|
||||||
|
n.Kind = "fconst"
|
||||||
|
case notIntConst | notNumConst | notType:
|
||||||
|
n.Kind = "sconst"
|
||||||
|
case notIntConst | notNumConst | notStrLiteral:
|
||||||
n.Kind = "type"
|
n.Kind = "type"
|
||||||
case notConst | notType:
|
case notIntConst | notNumConst | notStrLiteral | notType:
|
||||||
n.Kind = "not-type"
|
n.Kind = "not-type"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -431,7 +452,7 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
|
||||||
b.WriteString("#line 1 \"cgo-dwarf-inference\"\n")
|
b.WriteString("#line 1 \"cgo-dwarf-inference\"\n")
|
||||||
for i, n := range names {
|
for i, n := range names {
|
||||||
fmt.Fprintf(&b, "__typeof__(%s) *__cgo__%d;\n", n.C, i)
|
fmt.Fprintf(&b, "__typeof__(%s) *__cgo__%d;\n", n.C, i)
|
||||||
if n.Kind == "const" {
|
if n.Kind == "iconst" {
|
||||||
fmt.Fprintf(&b, "enum { __cgo_enum__%d = %s };\n", i, n.C)
|
fmt.Fprintf(&b, "enum { __cgo_enum__%d = %s };\n", i, n.C)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -440,9 +461,9 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
|
||||||
// names and values in its DWARF debug output. In case we're
|
// names and values in its DWARF debug output. In case we're
|
||||||
// using such a gcc, create a data block initialized with the values.
|
// using such a gcc, create a data block initialized with the values.
|
||||||
// We can read them out of the object file.
|
// We can read them out of the object file.
|
||||||
fmt.Fprintf(&b, "long long __cgodebug_data[] = {\n")
|
fmt.Fprintf(&b, "long long __cgodebug_ints[] = {\n")
|
||||||
for _, n := range names {
|
for _, n := range names {
|
||||||
if n.Kind == "const" {
|
if n.Kind == "iconst" {
|
||||||
fmt.Fprintf(&b, "\t%s,\n", n.C)
|
fmt.Fprintf(&b, "\t%s,\n", n.C)
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(&b, "\t0,\n")
|
fmt.Fprintf(&b, "\t0,\n")
|
||||||
|
|
@ -456,11 +477,19 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
|
||||||
fmt.Fprintf(&b, "\t1\n")
|
fmt.Fprintf(&b, "\t1\n")
|
||||||
fmt.Fprintf(&b, "};\n")
|
fmt.Fprintf(&b, "};\n")
|
||||||
|
|
||||||
d, bo, debugData := p.gccDebug(b.Bytes())
|
// do the same work for floats.
|
||||||
enumVal := make([]int64, len(debugData)/8)
|
fmt.Fprintf(&b, "double __cgodebug_floats[] = {\n")
|
||||||
for i := range enumVal {
|
for _, n := range names {
|
||||||
enumVal[i] = int64(bo.Uint64(debugData[i*8:]))
|
if n.Kind == "fconst" {
|
||||||
|
fmt.Fprintf(&b, "\t%s,\n", n.C)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(&b, "\t0,\n")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
fmt.Fprintf(&b, "\t1\n")
|
||||||
|
fmt.Fprintf(&b, "};\n")
|
||||||
|
|
||||||
|
d, ints, floats := p.gccDebug(b.Bytes())
|
||||||
|
|
||||||
// Scan DWARF info for top-level TagVariable entries with AttrName __cgo__i.
|
// Scan DWARF info for top-level TagVariable entries with AttrName __cgo__i.
|
||||||
types := make([]dwarf.Type, len(names))
|
types := make([]dwarf.Type, len(names))
|
||||||
|
|
@ -563,15 +592,22 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
|
||||||
n.Type = conv.Type(types[i], pos)
|
n.Type = conv.Type(types[i], pos)
|
||||||
if enums[i] != 0 && n.Type.EnumValues != nil {
|
if enums[i] != 0 && n.Type.EnumValues != nil {
|
||||||
k := fmt.Sprintf("__cgo_enum__%d", i)
|
k := fmt.Sprintf("__cgo_enum__%d", i)
|
||||||
n.Kind = "const"
|
n.Kind = "iconst"
|
||||||
n.Const = fmt.Sprintf("%#x", n.Type.EnumValues[k])
|
n.Const = fmt.Sprintf("%#x", n.Type.EnumValues[k])
|
||||||
// Remove injected enum to ensure the value will deep-compare
|
// Remove injected enum to ensure the value will deep-compare
|
||||||
// equally in future loads of the same constant.
|
// equally in future loads of the same constant.
|
||||||
delete(n.Type.EnumValues, k)
|
delete(n.Type.EnumValues, k)
|
||||||
}
|
}
|
||||||
// Prefer debug data over DWARF debug output, if we have it.
|
// Prefer debug data over DWARF debug output, if we have it.
|
||||||
if n.Kind == "const" && i < len(enumVal) {
|
switch n.Kind {
|
||||||
n.Const = fmt.Sprintf("%#x", enumVal[i])
|
case "iconst":
|
||||||
|
if i < len(ints) {
|
||||||
|
n.Const = fmt.Sprintf("%#x", ints[i])
|
||||||
|
}
|
||||||
|
case "fconst":
|
||||||
|
if i < len(floats) {
|
||||||
|
n.Const = fmt.Sprintf("%f", floats[i])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
conv.FinishType(pos)
|
conv.FinishType(pos)
|
||||||
|
|
@ -1050,7 +1086,7 @@ func (p *Package) rewriteRef(f *File) {
|
||||||
// are trying to do a ,err call. Also check that
|
// are trying to do a ,err call. Also check that
|
||||||
// functions are only used in calls.
|
// functions are only used in calls.
|
||||||
for _, r := range f.Ref {
|
for _, r := range f.Ref {
|
||||||
if r.Name.Kind == "const" && r.Name.Const == "" {
|
if r.Name.IsConst() && r.Name.Const == "" {
|
||||||
error_(r.Pos(), "unable to find value of constant C.%s", fixGo(r.Name.Go))
|
error_(r.Pos(), "unable to find value of constant C.%s", fixGo(r.Name.Go))
|
||||||
}
|
}
|
||||||
var expr ast.Expr = ast.NewIdent(r.Name.Mangle) // default
|
var expr ast.Expr = ast.NewIdent(r.Name.Mangle) // default
|
||||||
|
|
@ -1258,12 +1294,16 @@ func (p *Package) gccCmd() []string {
|
||||||
|
|
||||||
// gccDebug runs gcc -gdwarf-2 over the C program stdin and
|
// gccDebug runs gcc -gdwarf-2 over the C program stdin and
|
||||||
// returns the corresponding DWARF data and, if present, debug data block.
|
// returns the corresponding DWARF data and, if present, debug data block.
|
||||||
func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte) {
|
func (p *Package) gccDebug(stdin []byte) (d *dwarf.Data, ints []int64, floats []float64) {
|
||||||
runGcc(stdin, p.gccCmd())
|
runGcc(stdin, p.gccCmd())
|
||||||
|
|
||||||
isDebugData := func(s string) bool {
|
isDebugInts := func(s string) bool {
|
||||||
// Some systems use leading _ to denote non-assembly symbols.
|
// Some systems use leading _ to denote non-assembly symbols.
|
||||||
return s == "__cgodebug_data" || s == "___cgodebug_data"
|
return s == "__cgodebug_ints" || s == "___cgodebug_ints"
|
||||||
|
}
|
||||||
|
isDebugFloats := func(s string) bool {
|
||||||
|
// Some systems use leading _ to denote non-assembly symbols.
|
||||||
|
return s == "__cgodebug_floats" || s == "___cgodebug_floats"
|
||||||
}
|
}
|
||||||
|
|
||||||
if f, err := macho.Open(gccTmp()); err == nil {
|
if f, err := macho.Open(gccTmp()); err == nil {
|
||||||
|
|
@ -1272,24 +1312,43 @@ func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
|
fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
|
||||||
}
|
}
|
||||||
var data []byte
|
bo := f.ByteOrder
|
||||||
if f.Symtab != nil {
|
if f.Symtab != nil {
|
||||||
for i := range f.Symtab.Syms {
|
for i := range f.Symtab.Syms {
|
||||||
s := &f.Symtab.Syms[i]
|
s := &f.Symtab.Syms[i]
|
||||||
if isDebugData(s.Name) {
|
switch {
|
||||||
|
case isDebugInts(s.Name):
|
||||||
// Found it. Now find data section.
|
// Found it. Now find data section.
|
||||||
if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
|
if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
|
||||||
sect := f.Sections[i]
|
sect := f.Sections[i]
|
||||||
if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
|
if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
|
||||||
if sdat, err := sect.Data(); err == nil {
|
if sdat, err := sect.Data(); err == nil {
|
||||||
data = sdat[s.Value-sect.Addr:]
|
data := sdat[s.Value-sect.Addr:]
|
||||||
|
ints = make([]int64, len(data)/8)
|
||||||
|
for i := range ints {
|
||||||
|
ints[i] = int64(bo.Uint64(data[i*8:]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case isDebugFloats(s.Name):
|
||||||
|
// Found it. Now find data section.
|
||||||
|
if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
|
||||||
|
sect := f.Sections[i]
|
||||||
|
if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
|
||||||
|
if sdat, err := sect.Data(); err == nil {
|
||||||
|
data := sdat[s.Value-sect.Addr:]
|
||||||
|
floats = make([]float64, len(data)/8)
|
||||||
|
for i := range floats {
|
||||||
|
floats[i] = math.Float64frombits(bo.Uint64(data[i*8:]))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return d, f.ByteOrder, data
|
return d, ints, floats
|
||||||
}
|
}
|
||||||
|
|
||||||
if f, err := elf.Open(gccTmp()); err == nil {
|
if f, err := elf.Open(gccTmp()); err == nil {
|
||||||
|
|
@ -1298,25 +1357,44 @@ func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
|
fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
|
||||||
}
|
}
|
||||||
var data []byte
|
bo := f.ByteOrder
|
||||||
symtab, err := f.Symbols()
|
symtab, err := f.Symbols()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
for i := range symtab {
|
for i := range symtab {
|
||||||
s := &symtab[i]
|
s := &symtab[i]
|
||||||
if isDebugData(s.Name) {
|
switch {
|
||||||
|
case isDebugInts(s.Name):
|
||||||
// Found it. Now find data section.
|
// Found it. Now find data section.
|
||||||
if i := int(s.Section); 0 <= i && i < len(f.Sections) {
|
if i := int(s.Section); 0 <= i && i < len(f.Sections) {
|
||||||
sect := f.Sections[i]
|
sect := f.Sections[i]
|
||||||
if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
|
if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
|
||||||
if sdat, err := sect.Data(); err == nil {
|
if sdat, err := sect.Data(); err == nil {
|
||||||
data = sdat[s.Value-sect.Addr:]
|
data := sdat[s.Value-sect.Addr:]
|
||||||
|
ints = make([]int64, len(data)/8)
|
||||||
|
for i := range ints {
|
||||||
|
ints[i] = int64(bo.Uint64(data[i*8:]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case isDebugFloats(s.Name):
|
||||||
|
// Found it. Now find data section.
|
||||||
|
if i := int(s.Section); 0 <= i && i < len(f.Sections) {
|
||||||
|
sect := f.Sections[i]
|
||||||
|
if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
|
||||||
|
if sdat, err := sect.Data(); err == nil {
|
||||||
|
data := sdat[s.Value-sect.Addr:]
|
||||||
|
floats = make([]float64, len(data)/8)
|
||||||
|
for i := range floats {
|
||||||
|
floats[i] = math.Float64frombits(bo.Uint64(data[i*8:]))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return d, f.ByteOrder, data
|
return d, ints, floats
|
||||||
}
|
}
|
||||||
|
|
||||||
if f, err := pe.Open(gccTmp()); err == nil {
|
if f, err := pe.Open(gccTmp()); err == nil {
|
||||||
|
|
@ -1325,20 +1403,38 @@ func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
|
fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
|
||||||
}
|
}
|
||||||
var data []byte
|
bo := binary.LittleEndian
|
||||||
for _, s := range f.Symbols {
|
for _, s := range f.Symbols {
|
||||||
if isDebugData(s.Name) {
|
switch {
|
||||||
|
case isDebugInts(s.Name):
|
||||||
if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
|
if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
|
||||||
sect := f.Sections[i]
|
sect := f.Sections[i]
|
||||||
if s.Value < sect.Size {
|
if s.Value < sect.Size {
|
||||||
if sdat, err := sect.Data(); err == nil {
|
if sdat, err := sect.Data(); err == nil {
|
||||||
data = sdat[s.Value:]
|
data := sdat[s.Value:]
|
||||||
|
ints = make([]int64, len(data)/8)
|
||||||
|
for i := range ints {
|
||||||
|
ints[i] = int64(bo.Uint64(data[i*8:]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case isDebugFloats(s.Name):
|
||||||
|
if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
|
||||||
|
sect := f.Sections[i]
|
||||||
|
if s.Value < sect.Size {
|
||||||
|
if sdat, err := sect.Data(); err == nil {
|
||||||
|
data := sdat[s.Value:]
|
||||||
|
floats = make([]float64, len(data)/8)
|
||||||
|
for i := range floats {
|
||||||
|
floats[i] = math.Float64frombits(bo.Uint64(data[i*8:]))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return d, binary.LittleEndian, data
|
return d, ints, floats
|
||||||
}
|
}
|
||||||
|
|
||||||
fatalf("cannot parse gcc output %s as ELF, Mach-O, PE object", gccTmp())
|
fatalf("cannot parse gcc output %s as ELF, Mach-O, PE object", gccTmp())
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ type Name struct {
|
||||||
Mangle string // name used in generated Go
|
Mangle string // name used in generated Go
|
||||||
C string // name used in C
|
C string // name used in C
|
||||||
Define string // #define expansion
|
Define string // #define expansion
|
||||||
Kind string // "const", "type", "var", "fpvar", "func", "not-type"
|
Kind string // "iconst", "fconst", "sconst", "type", "var", "fpvar", "func", "not-type"
|
||||||
Type *Type // the type of xxx
|
Type *Type // the type of xxx
|
||||||
FuncType *FuncType
|
FuncType *FuncType
|
||||||
AddError bool
|
AddError bool
|
||||||
|
|
@ -100,6 +100,11 @@ func (n *Name) IsVar() bool {
|
||||||
return n.Kind == "var" || n.Kind == "fpvar"
|
return n.Kind == "var" || n.Kind == "fpvar"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsConst reports whether Kind is either "iconst", "fconst" or "sconst"
|
||||||
|
func (n *Name) IsConst() bool {
|
||||||
|
return n.Kind == "iconst" || n.Kind == "fconst" || n.Kind == "sconst"
|
||||||
|
}
|
||||||
|
|
||||||
// A ExpFunc is an exported function, callable from C.
|
// A ExpFunc is an exported function, callable from C.
|
||||||
// Such functions are identified in the Go input file
|
// Such functions are identified in the Go input file
|
||||||
// by doc comments containing the line //export ExpName
|
// by doc comments containing the line //export ExpName
|
||||||
|
|
|
||||||
|
|
@ -185,7 +185,7 @@ func (p *Package) writeDefs() {
|
||||||
for _, key := range nameKeys(p.Name) {
|
for _, key := range nameKeys(p.Name) {
|
||||||
n := p.Name[key]
|
n := p.Name[key]
|
||||||
if n.Const != "" {
|
if n.Const != "" {
|
||||||
fmt.Fprintf(fgo2, "const _Cconst_%s = %s\n", n.Go, n.Const)
|
fmt.Fprintf(fgo2, "const _C%s_%s = %s\n", n.Kind, n.Go, n.Const)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Fprintf(fgo2, "\n")
|
fmt.Fprintf(fgo2, "\n")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue