Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(258)

Unified Diff: src/cmd/cgo/gcc.go

Issue 4607045: code review 4607045: cgo: handle new Apple LLVM-based gcc from Xcode 4.2 (Closed)
Patch Set: diff -r 83bf1e008e3e https://go.googlecode.com/hg Created 12 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/pkg/debug/dwarf/type.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/cmd/cgo/gcc.go
===================================================================
--- a/src/cmd/cgo/gcc.go
+++ b/src/cmd/cgo/gcc.go
@@ -13,6 +13,7 @@
"debug/elf"
"debug/macho"
"debug/pe"
+ "encoding/binary"
"flag"
"fmt"
"go/ast"
@@ -477,7 +478,27 @@
fmt.Fprintf(&b, "enum { __cgo_enum__%d = %s };\n", i, n.C)
}
}
- d := p.gccDebug(b.Bytes())
+
+ // Apple's LLVM-based gcc does not include the enumeration
+ // names and values in its DWARF debug output. In case we're
+ // using such a gcc, create a data block initialized with the values.
+ // We can read them out of the object file.
+ fmt.Fprintf(&b, "long long __cgodebug_data[] = {\n")
+ for _, n := range names {
+ if n.Kind == "const" {
+ fmt.Fprintf(&b, "\t%s,\n", n.C)
+ } else {
+ fmt.Fprintf(&b, "\t0,\n")
+ }
+ }
+ fmt.Fprintf(&b, "\t0\n")
+ fmt.Fprintf(&b, "};\n")
+
+ d, bo, debugData := p.gccDebug(b.Bytes())
+ enumVal := make([]int64, len(debugData)/8)
+ for i := range enumVal {
+ enumVal[i] = int64(bo.Uint64(debugData[i*8:]))
+ }
// Scan DWARF info for top-level TagVariable entries with AttrName __cgo__i.
types := make([]dwarf.Type, len(names))
@@ -569,9 +590,12 @@
// Remove injected enum to ensure the value will deep-compare
// equally in future loads of the same constant.
n.Type.EnumValues[k] = 0, false
+ } else if n.Kind == "const" && i < len(enumVal) {
+ n.Const = strconv.Itoa64(enumVal[i])
}
}
}
+
}
// rewriteRef rewrites all the C.xxx references in f.AST to refer to the
@@ -593,6 +617,9 @@
// are trying to do a ,err call. Also check that
// functions are only used in calls.
for _, r := range f.Ref {
+ if r.Name.Kind == "const" && r.Name.Const == "" {
+ error(r.Pos(), "unable to find value of constant C.%s", r.Name.Go)
+ }
var expr ast.Expr = ast.NewIdent(r.Name.Mangle) // default
switch r.Context {
case "call", "call2":
@@ -692,29 +719,57 @@
}
// gccDebug runs gcc -gdwarf-2 over the C program stdin and
-// returns the corresponding DWARF data and any messages
-// printed to standard error.
-func (p *Package) gccDebug(stdin []byte) *dwarf.Data {
+// returns the corresponding DWARF data and, if present, debug data block.
+func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte) {
runGcc(stdin, p.gccCmd())
- // Try to parse f as ELF and Mach-O and hope one works.
- var f interface {
- DWARF() (*dwarf.Data, os.Error)
- }
- var err os.Error
- if f, err = elf.Open(gccTmp); err != nil {
- if f, err = macho.Open(gccTmp); err != nil {
- if f, err = pe.Open(gccTmp); err != nil {
- fatalf("cannot parse gcc output %s as ELF or Mach-O or PE object", gccTmp)
+ if f, err := macho.Open(gccTmp); err == nil {
+ d, err := f.DWARF()
+ if err != nil {
+ fatalf("cannot load DWARF output from %s: %v", gccTmp, err)
+ }
+ var data []byte
+ if f.Symtab != nil {
+ for i := range f.Symtab.Syms {
+ s := &f.Symtab.Syms[i]
+ // Mach-O still uses a leading _ to denote non-assembly symbols.
+ if s.Name == "_"+"__cgodebug_data" {
+ // 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:]
+ }
+ }
+ }
+ }
}
}
+ return d, f.ByteOrder, data
}
- d, err := f.DWARF()
- if err != nil {
- fatalf("cannot load DWARF debug information from %s: %s", gccTmp, err)
+ // Can skip debug data block in ELF and PE for now.
+ // The DWARF information is complete.
+
+ if f, err := elf.Open(gccTmp); err == nil {
+ d, err := f.DWARF()
+ if err != nil {
+ fatalf("cannot load DWARF output from %s: %v", gccTmp, err)
+ }
+ return d, f.ByteOrder, nil
}
- return d
+
+ if f, err := pe.Open(gccTmp); err == nil {
+ d, err := f.DWARF()
+ if err != nil {
+ fatalf("cannot load DWARF output from %s: %v", gccTmp, err)
+ }
+ return d, binary.LittleEndian, nil
+ }
+
+ fatalf("cannot parse gcc output %s as ELF, Mach-O, PE object", gccTmp)
+ panic("not reached")
}
// gccDefines runs gcc -E -dM -xc - over the C program stdin
« no previous file with comments | « no previous file | src/pkg/debug/dwarf/type.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b