Commit 1c729599 authored by Robert Griesemer's avatar Robert Griesemer

1) Change default gofmt default settings for

                  parsing and printing to new syntax.

                  Use -oldparser to parse the old syntax,
                  use -oldprinter to print the old syntax.

               2) Change default gofmt formatting settings
                  to use tabs for indentation only and to use
                  spaces for alignment. This will make the code
                  alignment insensitive to an editor's tabwidth.

                  Use -spaces=false to use tabs for alignment.

               3) Manually changed src/exp/parser/parser_test.go
                  so that it doesn't try to parse the parser's
                  source files using the old syntax (they have
                  new syntax now).

               4) gofmt -w src misc test/bench

	       2nd set of files.

R=rsc
CC=golang-dev
https://golang.org/cl/179067
parent d122bb21
...@@ -7,20 +7,20 @@ ...@@ -7,20 +7,20 @@
package dwarf package dwarf
import ( import (
"encoding/binary"; "encoding/binary"
"os"; "os"
"strconv"; "strconv"
) )
// Data buffer being decoded. // Data buffer being decoded.
type buf struct { type buf struct {
dwarf *Data; dwarf *Data
order binary.ByteOrder; order binary.ByteOrder
name string; name string
off Offset; off Offset
data []byte; data []byte
addrsize int; addrsize int
err os.Error; err os.Error
} }
func makeBuf(d *Data, name string, off Offset, data []byte, addrsize int) buf { func makeBuf(d *Data, name string, off Offset, data []byte, addrsize int) buf {
...@@ -29,24 +29,24 @@ func makeBuf(d *Data, name string, off Offset, data []byte, addrsize int) buf { ...@@ -29,24 +29,24 @@ func makeBuf(d *Data, name string, off Offset, data []byte, addrsize int) buf {
func (b *buf) uint8() uint8 { func (b *buf) uint8() uint8 {
if len(b.data) < 1 { if len(b.data) < 1 {
b.error("underflow"); b.error("underflow")
return 0; return 0
} }
val := b.data[0]; val := b.data[0]
b.data = b.data[1:]; b.data = b.data[1:]
b.off++; b.off++
return val; return val
} }
func (b *buf) bytes(n int) []byte { func (b *buf) bytes(n int) []byte {
if len(b.data) < n { if len(b.data) < n {
b.error("underflow"); b.error("underflow")
return nil; return nil
} }
data := b.data[0:n]; data := b.data[0:n]
b.data = b.data[n:]; b.data = b.data[n:]
b.off += Offset(n); b.off += Offset(n)
return data; return data
} }
func (b *buf) skip(n int) { b.bytes(n) } func (b *buf) skip(n int) { b.bytes(n) }
...@@ -54,70 +54,70 @@ func (b *buf) skip(n int) { b.bytes(n) } ...@@ -54,70 +54,70 @@ func (b *buf) skip(n int) { b.bytes(n) }
func (b *buf) string() string { func (b *buf) string() string {
for i := 0; i < len(b.data); i++ { for i := 0; i < len(b.data); i++ {
if b.data[i] == 0 { if b.data[i] == 0 {
s := string(b.data[0:i]); s := string(b.data[0:i])
b.data = b.data[i+1:]; b.data = b.data[i+1:]
b.off += Offset(i + 1); b.off += Offset(i + 1)
return s; return s
} }
} }
b.error("underflow"); b.error("underflow")
return ""; return ""
} }
func (b *buf) uint16() uint16 { func (b *buf) uint16() uint16 {
a := b.bytes(2); a := b.bytes(2)
if a == nil { if a == nil {
return 0 return 0
} }
return b.order.Uint16(a); return b.order.Uint16(a)
} }
func (b *buf) uint32() uint32 { func (b *buf) uint32() uint32 {
a := b.bytes(4); a := b.bytes(4)
if a == nil { if a == nil {
return 0 return 0
} }
return b.order.Uint32(a); return b.order.Uint32(a)
} }
func (b *buf) uint64() uint64 { func (b *buf) uint64() uint64 {
a := b.bytes(8); a := b.bytes(8)
if a == nil { if a == nil {
return 0 return 0
} }
return b.order.Uint64(a); return b.order.Uint64(a)
} }
// Read a varint, which is 7 bits per byte, little endian. // Read a varint, which is 7 bits per byte, little endian.
// the 0x80 bit means read another byte. // the 0x80 bit means read another byte.
func (b *buf) varint() (c uint64, bits uint) { func (b *buf) varint() (c uint64, bits uint) {
for i := 0; i < len(b.data); i++ { for i := 0; i < len(b.data); i++ {
byte := b.data[i]; byte := b.data[i]
c |= uint64(byte&0x7F) << bits; c |= uint64(byte&0x7F) << bits
bits += 7; bits += 7
if byte&0x80 == 0 { if byte&0x80 == 0 {
b.off += Offset(i + 1); b.off += Offset(i + 1)
b.data = b.data[i+1:]; b.data = b.data[i+1:]
return c, bits; return c, bits
} }
} }
return 0, 0; return 0, 0
} }
// Unsigned int is just a varint. // Unsigned int is just a varint.
func (b *buf) uint() uint64 { func (b *buf) uint() uint64 {
x, _ := b.varint(); x, _ := b.varint()
return x; return x
} }
// Signed int is a sign-extended varint. // Signed int is a sign-extended varint.
func (b *buf) int() int64 { func (b *buf) int() int64 {
ux, bits := b.varint(); ux, bits := b.varint()
x := int64(ux); x := int64(ux)
if x&(1<<(bits-1)) != 0 { if x&(1<<(bits-1)) != 0 {
x |= -1 << bits x |= -1 << bits
} }
return x; return x
} }
// Address-sized uint. // Address-sized uint.
...@@ -132,21 +132,21 @@ func (b *buf) addr() uint64 { ...@@ -132,21 +132,21 @@ func (b *buf) addr() uint64 {
case 8: case 8:
return uint64(b.uint64()) return uint64(b.uint64())
} }
b.error("unknown address size"); b.error("unknown address size")
return 0; return 0
} }
func (b *buf) error(s string) { func (b *buf) error(s string) {
if b.err == nil { if b.err == nil {
b.data = nil; b.data = nil
b.err = DecodeError{b.name, b.off, s}; b.err = DecodeError{b.name, b.off, s}
} }
} }
type DecodeError struct { type DecodeError struct {
Name string; Name string
Offset Offset; Offset Offset
Error string; Error string
} }
func (e DecodeError) String() string { func (e DecodeError) String() string {
......
This diff is collapsed.
...@@ -14,14 +14,14 @@ import "os" ...@@ -14,14 +14,14 @@ import "os"
// a single entry's description: a sequence of attributes // a single entry's description: a sequence of attributes
type abbrev struct { type abbrev struct {
tag Tag; tag Tag
children bool; children bool
field []afield; field []afield
} }
type afield struct { type afield struct {
attr Attr; attr Attr
fmt format; fmt format
} }
// a map from entry format ids to their descriptions // a map from entry format ids to their descriptions
...@@ -34,74 +34,74 @@ func (d *Data) parseAbbrev(off uint32) (abbrevTable, os.Error) { ...@@ -34,74 +34,74 @@ func (d *Data) parseAbbrev(off uint32) (abbrevTable, os.Error) {
return m, nil return m, nil
} }
data := d.abbrev; data := d.abbrev
if off > uint32(len(data)) { if off > uint32(len(data)) {
data = nil data = nil
} else { } else {
data = data[off:] data = data[off:]
} }
b := makeBuf(d, "abbrev", 0, data, 0); b := makeBuf(d, "abbrev", 0, data, 0)
// Error handling is simplified by the buf getters // Error handling is simplified by the buf getters
// returning an endless stream of 0s after an error. // returning an endless stream of 0s after an error.
m := make(abbrevTable); m := make(abbrevTable)
for { for {
// Table ends with id == 0. // Table ends with id == 0.
id := uint32(b.uint()); id := uint32(b.uint())
if id == 0 { if id == 0 {
break break
} }
// Walk over attributes, counting. // Walk over attributes, counting.
n := 0; n := 0
b1 := b; // Read from copy of b. b1 := b // Read from copy of b.
b1.uint(); b1.uint()
b1.uint8(); b1.uint8()
for { for {
tag := b1.uint(); tag := b1.uint()
fmt := b1.uint(); fmt := b1.uint()
if tag == 0 && fmt == 0 { if tag == 0 && fmt == 0 {
break break
} }
n++; n++
} }
if b1.err != nil { if b1.err != nil {
return nil, b1.err return nil, b1.err
} }
// Walk over attributes again, this time writing them down. // Walk over attributes again, this time writing them down.
var a abbrev; var a abbrev
a.tag = Tag(b.uint()); a.tag = Tag(b.uint())
a.children = b.uint8() != 0; a.children = b.uint8() != 0
a.field = make([]afield, n); a.field = make([]afield, n)
for i := range a.field { for i := range a.field {
a.field[i].attr = Attr(b.uint()); a.field[i].attr = Attr(b.uint())
a.field[i].fmt = format(b.uint()); a.field[i].fmt = format(b.uint())
} }
b.uint(); b.uint()
b.uint(); b.uint()
m[id] = a; m[id] = a
} }
if b.err != nil { if b.err != nil {
return nil, b.err return nil, b.err
} }
d.abbrevCache[off] = m; d.abbrevCache[off] = m
return m, nil; return m, nil
} }
// An entry is a sequence of attribute/value pairs. // An entry is a sequence of attribute/value pairs.
type Entry struct { type Entry struct {
Offset Offset; // offset of Entry in DWARF info Offset Offset // offset of Entry in DWARF info
Tag Tag; // tag (kind of Entry) Tag Tag // tag (kind of Entry)
Children bool; // whether Entry is followed by children Children bool // whether Entry is followed by children
Field []Field; Field []Field
} }
// A Field is a single attribute/value pair in an Entry. // A Field is a single attribute/value pair in an Entry.
type Field struct { type Field struct {
Attr Attr; Attr Attr
Val interface{}; Val interface{}
} }
// Val returns the value associated with attribute Attr in Entry, // Val returns the value associated with attribute Attr in Entry,
...@@ -117,7 +117,7 @@ func (e *Entry) Val(a Attr) interface{} { ...@@ -117,7 +117,7 @@ func (e *Entry) Val(a Attr) interface{} {
return f.Val return f.Val
} }
} }
return nil; return nil
} }
// An Offset represents the location of an Entry within the DWARF info. // An Offset represents the location of an Entry within the DWARF info.
...@@ -127,25 +127,25 @@ type Offset uint32 ...@@ -127,25 +127,25 @@ type Offset uint32
// Entry reads a single entry from buf, decoding // Entry reads a single entry from buf, decoding
// according to the given abbreviation table. // according to the given abbreviation table.
func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry { func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry {
off := b.off; off := b.off
id := uint32(b.uint()); id := uint32(b.uint())
if id == 0 { if id == 0 {
return &Entry{} return &Entry{}
} }
a, ok := atab[id]; a, ok := atab[id]
if !ok { if !ok {
b.error("unknown abbreviation table index"); b.error("unknown abbreviation table index")
return nil; return nil
} }
e := &Entry{ e := &Entry{
Offset: off, Offset: off,
Tag: a.tag, Tag: a.tag,
Children: a.children, Children: a.children,
Field: make([]Field, len(a.field)), Field: make([]Field, len(a.field)),
}; }
for i := range e.Field { for i := range e.Field {
e.Field[i].Attr = a.field[i].attr; e.Field[i].Attr = a.field[i].attr
fmt := a.field[i].fmt; fmt := a.field[i].fmt
if fmt == formIndirect { if fmt == formIndirect {
fmt = format(b.uint()) fmt = format(b.uint())
} }
...@@ -204,24 +204,24 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry { ...@@ -204,24 +204,24 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry {
case formString: case formString:
val = b.string() val = b.string()
case formStrp: case formStrp:
off := b.uint32(); // offset into .debug_str off := b.uint32() // offset into .debug_str
if b.err != nil { if b.err != nil {
return nil return nil
} }
b1 := makeBuf(b.dwarf, "str", 0, b.dwarf.str, 0); b1 := makeBuf(b.dwarf, "str", 0, b.dwarf.str, 0)
b1.skip(int(off)); b1.skip(int(off))
val = b1.string(); val = b1.string()
if b1.err != nil { if b1.err != nil {
b.err = b1.err; b.err = b1.err
return nil; return nil
} }
} }
e.Field[i].Val = val; e.Field[i].Val = val
} }
if b.err != nil { if b.err != nil {
return nil return nil
} }
return e; return e
} }
// A Reader allows reading Entry structures from a DWARF ``info'' section. // A Reader allows reading Entry structures from a DWARF ``info'' section.
...@@ -230,58 +230,58 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry { ...@@ -230,58 +230,58 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry {
// If an entry has children, its Children field will be true, and the children // If an entry has children, its Children field will be true, and the children
// follow, terminated by an Entry with Tag 0. // follow, terminated by an Entry with Tag 0.
type Reader struct { type Reader struct {
b buf; b buf
d *Data; d *Data
err os.Error; err os.Error
unit int; unit int
lastChildren bool; // .Children of last entry returned by Next lastChildren bool // .Children of last entry returned by Next
lastSibling Offset; // .Val(AttrSibling) of last entry returned by Next lastSibling Offset // .Val(AttrSibling) of last entry returned by Next
} }
// Reader returns a new Reader for Data. // Reader returns a new Reader for Data.
// The reader is positioned at byte offset 0 in the DWARF ``info'' section. // The reader is positioned at byte offset 0 in the DWARF ``info'' section.
func (d *Data) Reader() *Reader { func (d *Data) Reader() *Reader {
r := &Reader{d: d}; r := &Reader{d: d}
r.Seek(0); r.Seek(0)
return r; return r
} }
// Seek positions the Reader at offset off in the encoded entry stream. // Seek positions the Reader at offset off in the encoded entry stream.
// Offset 0 can be used to denote the first entry. // Offset 0 can be used to denote the first entry.
func (r *Reader) Seek(off Offset) { func (r *Reader) Seek(off Offset) {
d := r.d; d := r.d
r.err = nil; r.err = nil
r.lastChildren = false; r.lastChildren = false
if off == 0 { if off == 0 {
if len(d.unit) == 0 { if len(d.unit) == 0 {
return return
} }
u := &d.unit[0]; u := &d.unit[0]
r.unit = 0; r.unit = 0
r.b = makeBuf(r.d, "info", u.off, u.data, u.addrsize); r.b = makeBuf(r.d, "info", u.off, u.data, u.addrsize)
return; return
} }
// TODO(rsc): binary search (maybe a new package) // TODO(rsc): binary search (maybe a new package)
var i int; var i int
var u *unit; var u *unit
for i = range d.unit { for i = range d.unit {
u = &d.unit[i]; u = &d.unit[i]
if u.off <= off && off < u.off+Offset(len(u.data)) { if u.off <= off && off < u.off+Offset(len(u.data)) {
r.unit = i; r.unit = i
r.b = makeBuf(r.d, "info", off, u.data[off-u.off:], u.addrsize); r.b = makeBuf(r.d, "info", off, u.data[off-u.off:], u.addrsize)
return; return
} }
} }
r.err = os.NewError("offset out of range"); r.err = os.NewError("offset out of range")
} }
// maybeNextUnit advances to the next unit if this one is finished. // maybeNextUnit advances to the next unit if this one is finished.
func (r *Reader) maybeNextUnit() { func (r *Reader) maybeNextUnit() {
for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) { for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) {
r.unit++; r.unit++
u := &r.d.unit[r.unit]; u := &r.d.unit[r.unit]
r.b = makeBuf(r.d, "info", u.off, u.data, u.addrsize); r.b = makeBuf(r.d, "info", u.off, u.data, u.addrsize)
} }
} }
...@@ -293,25 +293,25 @@ func (r *Reader) Next() (*Entry, os.Error) { ...@@ -293,25 +293,25 @@ func (r *Reader) Next() (*Entry, os.Error) {
if r.err != nil { if r.err != nil {
return nil, r.err return nil, r.err
} }
r.maybeNextUnit(); r.maybeNextUnit()
if len(r.b.data) == 0 { if len(r.b.data) == 0 {
return nil, nil return nil, nil
} }
u := &r.d.unit[r.unit]; u := &r.d.unit[r.unit]
e := r.b.entry(u.atable, u.base); e := r.b.entry(u.atable, u.base)
if r.b.err != nil { if r.b.err != nil {
r.err = r.b.err; r.err = r.b.err
return nil, r.err; return nil, r.err
} }
if e != nil { if e != nil {
r.lastChildren = e.Children; r.lastChildren = e.Children
if r.lastChildren { if r.lastChildren {
r.lastSibling, _ = e.Val(AttrSibling).(Offset) r.lastSibling, _ = e.Val(AttrSibling).(Offset)
} }
} else { } else {
r.lastChildren = false r.lastChildren = false
} }
return e, nil; return e, nil
} }
// SkipChildren skips over the child entries associated with // SkipChildren skips over the child entries associated with
...@@ -327,12 +327,12 @@ func (r *Reader) SkipChildren() { ...@@ -327,12 +327,12 @@ func (r *Reader) SkipChildren() {
// sibling, so we can avoid decoding the // sibling, so we can avoid decoding the
// child subtrees. // child subtrees.
if r.lastSibling >= r.b.off { if r.lastSibling >= r.b.off {
r.Seek(r.lastSibling); r.Seek(r.lastSibling)
return; return
} }
for { for {
e, err := r.Next(); e, err := r.Next()
if err != nil || e == nil || e.Tag == 0 { if err != nil || e == nil || e.Tag == 0 {
break break
} }
......
...@@ -8,29 +8,29 @@ ...@@ -8,29 +8,29 @@
package dwarf package dwarf
import ( import (
"encoding/binary"; "encoding/binary"
"os"; "os"
) )
// Data represents the DWARF debugging information // Data represents the DWARF debugging information
// loaded from an executable file (for example, an ELF or Mach-O executable). // loaded from an executable file (for example, an ELF or Mach-O executable).
type Data struct { type Data struct {
// raw data // raw data
abbrev []byte; abbrev []byte
aranges []byte; aranges []byte
frame []byte; frame []byte
info []byte; info []byte
line []byte; line []byte
pubnames []byte; pubnames []byte
ranges []byte; ranges []byte
str []byte; str []byte
// parsed data // parsed data
abbrevCache map[uint32]abbrevTable; abbrevCache map[uint32]abbrevTable
addrsize int; addrsize int
order binary.ByteOrder; order binary.ByteOrder
typeCache map[Offset]Type; typeCache map[Offset]Type
unit []unit; unit []unit
} }
// New returns a new Data object initialized from the given parameters. // New returns a new Data object initialized from the given parameters.
...@@ -52,14 +52,14 @@ func New(abbrev, aranges, frame, info, line, pubnames, ranges, str []byte) (*Dat ...@@ -52,14 +52,14 @@ func New(abbrev, aranges, frame, info, line, pubnames, ranges, str []byte) (*Dat
str: str, str: str,
abbrevCache: make(map[uint32]abbrevTable), abbrevCache: make(map[uint32]abbrevTable),
typeCache: make(map[Offset]Type), typeCache: make(map[Offset]Type),
}; }
// Sniff .debug_info to figure out byte order. // Sniff .debug_info to figure out byte order.
// bytes 4:6 are the version, a tiny 16-bit number (1, 2, 3). // bytes 4:6 are the version, a tiny 16-bit number (1, 2, 3).
if len(d.info) < 6 { if len(d.info) < 6 {
return nil, DecodeError{"info", Offset(len(d.info)), "too short"} return nil, DecodeError{"info", Offset(len(d.info)), "too short"}
} }
x, y := d.info[4], d.info[5]; x, y := d.info[4], d.info[5]
switch { switch {
case x == 0 && y == 0: case x == 0 && y == 0:
return nil, DecodeError{"info", 4, "unsupported version 0"} return nil, DecodeError{"info", 4, "unsupported version 0"}
...@@ -71,10 +71,10 @@ func New(abbrev, aranges, frame, info, line, pubnames, ranges, str []byte) (*Dat ...@@ -71,10 +71,10 @@ func New(abbrev, aranges, frame, info, line, pubnames, ranges, str []byte) (*Dat
return nil, DecodeError{"info", 4, "cannot determine byte order"} return nil, DecodeError{"info", 4, "cannot determine byte order"}
} }
u, err := d.parseUnits(); u, err := d.parseUnits()
if err != nil { if err != nil {
return nil, err return nil, err
} }
d.unit = u; d.unit = u
return d, nil; return d, nil
} }
This diff is collapsed.
...@@ -5,10 +5,10 @@ ...@@ -5,10 +5,10 @@
package dwarf_test package dwarf_test
import ( import (
. "debug/dwarf"; . "debug/dwarf"
"debug/elf"; "debug/elf"
"debug/macho"; "debug/macho"
"testing"; "testing"
) )
var typedefTests = map[string]string{ var typedefTests = map[string]string{
...@@ -30,29 +30,29 @@ var typedefTests = map[string]string{ ...@@ -30,29 +30,29 @@ var typedefTests = map[string]string{
} }
func elfData(t *testing.T, name string) *Data { func elfData(t *testing.T, name string) *Data {
f, err := elf.Open(name); f, err := elf.Open(name)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
d, err := f.DWARF(); d, err := f.DWARF()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
return d; return d
} }
func machoData(t *testing.T, name string) *Data { func machoData(t *testing.T, name string) *Data {
f, err := macho.Open(name); f, err := macho.Open(name)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
d, err := f.DWARF(); d, err := f.DWARF()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
return d; return d
} }
...@@ -63,10 +63,10 @@ func TestTypedefsMachO(t *testing.T) { ...@@ -63,10 +63,10 @@ func TestTypedefsMachO(t *testing.T) {
} }
func testTypedefs(t *testing.T, d *Data) { func testTypedefs(t *testing.T, d *Data) {
r := d.Reader(); r := d.Reader()
seen := make(map[string]bool); seen := make(map[string]bool)
for { for {
e, err := r.Next(); e, err := r.Next()
if err != nil { if err != nil {
t.Fatal("r.Next:", err) t.Fatal("r.Next:", err)
} }
...@@ -74,12 +74,12 @@ func testTypedefs(t *testing.T, d *Data) { ...@@ -74,12 +74,12 @@ func testTypedefs(t *testing.T, d *Data) {
break break
} }
if e.Tag == TagTypedef { if e.Tag == TagTypedef {
typ, err := d.Type(e.Offset); typ, err := d.Type(e.Offset)
if err != nil { if err != nil {
t.Fatal("d.Type:", err) t.Fatal("d.Type:", err)
} }
t1 := typ.(*TypedefType); t1 := typ.(*TypedefType)
var typstr string; var typstr string
if ts, ok := t1.Type.(*StructType); ok { if ts, ok := t1.Type.(*StructType); ok {
typstr = ts.Defn() typstr = ts.Defn()
} else { } else {
...@@ -90,7 +90,7 @@ func testTypedefs(t *testing.T, d *Data) { ...@@ -90,7 +90,7 @@ func testTypedefs(t *testing.T, d *Data) {
if _, ok := seen[t1.Name]; ok { if _, ok := seen[t1.Name]; ok {
t.Errorf("multiple definitions for %s", t1.Name) t.Errorf("multiple definitions for %s", t1.Name)
} }
seen[t1.Name] = true; seen[t1.Name] = true
if typstr != want { if typstr != want {
t.Errorf("%s:\n\thave %s\n\twant %s", t1.Name, typstr, want) t.Errorf("%s:\n\thave %s\n\twant %s", t1.Name, typstr, want)
} }
......
...@@ -5,58 +5,58 @@ ...@@ -5,58 +5,58 @@
package dwarf package dwarf
import ( import (
"os"; "os"
"strconv"; "strconv"
) )
// DWARF debug info is split into a sequence of compilation units. // DWARF debug info is split into a sequence of compilation units.
// Each unit has its own abbreviation table and address size. // Each unit has its own abbreviation table and address size.
type unit struct { type unit struct {
base Offset; // byte offset of header within the aggregate info base Offset // byte offset of header within the aggregate info
off Offset; // byte offset of data within the aggregate info off Offset // byte offset of data within the aggregate info
data []byte; data []byte
atable abbrevTable; atable abbrevTable
addrsize int; addrsize int
} }
func (d *Data) parseUnits() ([]unit, os.Error) { func (d *Data) parseUnits() ([]unit, os.Error) {
// Count units. // Count units.
nunit := 0; nunit := 0
b := makeBuf(d, "info", 0, d.info, 0); b := makeBuf(d, "info", 0, d.info, 0)
for len(b.data) > 0 { for len(b.data) > 0 {
b.skip(int(b.uint32())); b.skip(int(b.uint32()))
nunit++; nunit++
} }
if b.err != nil { if b.err != nil {
return nil, b.err return nil, b.err
} }
// Again, this time writing them down. // Again, this time writing them down.
b = makeBuf(d, "info", 0, d.info, 0); b = makeBuf(d, "info", 0, d.info, 0)
units := make([]unit, nunit); units := make([]unit, nunit)
for i := range units { for i := range units {
u := &units[i]; u := &units[i]
u.base = b.off; u.base = b.off
n := b.uint32(); n := b.uint32()
if vers := b.uint16(); vers != 2 { if vers := b.uint16(); vers != 2 {
b.error("unsupported DWARF version " + strconv.Itoa(int(vers))); b.error("unsupported DWARF version " + strconv.Itoa(int(vers)))
break; break
} }
atable, err := d.parseAbbrev(b.uint32()); atable, err := d.parseAbbrev(b.uint32())
if err != nil { if err != nil {
if b.err == nil { if b.err == nil {
b.err = err b.err = err
} }
break; break
} }
u.atable = atable; u.atable = atable
u.addrsize = int(b.uint8()); u.addrsize = int(b.uint8())
u.off = b.off; u.off = b.off
u.data = b.bytes(int(n - (2 + 4 + 1))); u.data = b.bytes(int(n - (2 + 4 + 1)))
} }
if b.err != nil { if b.err != nil {
return nil, b.err return nil, b.err
} }
return units, nil; return units, nil
} }
This diff is collapsed.
...@@ -5,13 +5,13 @@ ...@@ -5,13 +5,13 @@
package elf package elf
import ( import (
"fmt"; "fmt"
"testing"; "testing"
) )
type nameTest struct { type nameTest struct {
val interface{}; val interface{}
str string; str string
} }
var nameTests = []nameTest{ var nameTests = []nameTest{
...@@ -41,7 +41,7 @@ var nameTests = []nameTest{ ...@@ -41,7 +41,7 @@ var nameTests = []nameTest{
func TestNames(t *testing.T) { func TestNames(t *testing.T) {
for i, tt := range nameTests { for i, tt := range nameTests {
s := fmt.Sprint(tt.val); s := fmt.Sprint(tt.val)
if s != tt.str { if s != tt.str {
t.Errorf("#%d: want %q have %q", i, s, tt.str) t.Errorf("#%d: want %q have %q", i, s, tt.str)
} }
......
This diff is collapsed.
...@@ -5,16 +5,16 @@ ...@@ -5,16 +5,16 @@
package elf package elf
import ( import (
"debug/dwarf"; "debug/dwarf"
"encoding/binary"; "encoding/binary"
"reflect"; "reflect"
"testing"; "testing"
) )
type fileTest struct { type fileTest struct {
file string; file string
hdr FileHeader; hdr FileHeader
sections []SectionHeader; sections []SectionHeader
} }
var fileTests = []fileTest{ var fileTests = []fileTest{
...@@ -101,28 +101,28 @@ var fileTests = []fileTest{ ...@@ -101,28 +101,28 @@ var fileTests = []fileTest{
func TestOpen(t *testing.T) { func TestOpen(t *testing.T) {
for i := range fileTests { for i := range fileTests {
tt := &fileTests[i]; tt := &fileTests[i]
f, err := Open(tt.file); f, err := Open(tt.file)
if err != nil { if err != nil {
t.Error(err); t.Error(err)
continue; continue
} }
if !reflect.DeepEqual(f.FileHeader, tt.hdr) { if !reflect.DeepEqual(f.FileHeader, tt.hdr) {
t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr); t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr)
continue; continue
} }
for i, s := range f.Sections { for i, s := range f.Sections {
if i >= len(tt.sections) { if i >= len(tt.sections) {
break break
} }
sh := &tt.sections[i]; sh := &tt.sections[i]
if !reflect.DeepEqual(&s.SectionHeader, sh) { if !reflect.DeepEqual(&s.SectionHeader, sh) {
t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, &s.SectionHeader, sh) t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, &s.SectionHeader, sh)
} }
} }
tn := len(tt.sections); tn := len(tt.sections)
fn := len(f.Sections); fn := len(f.Sections)
if tn != fn { if tn != fn {
t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn) t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn)
} }
...@@ -130,8 +130,8 @@ func TestOpen(t *testing.T) { ...@@ -130,8 +130,8 @@ func TestOpen(t *testing.T) {
} }
type relocationTest struct { type relocationTest struct {
file string; file string
firstEntry *dwarf.Entry; firstEntry *dwarf.Entry
} }
var relocationTests = []relocationTest{ var relocationTests = []relocationTest{
...@@ -151,30 +151,30 @@ var relocationTests = []relocationTest{ ...@@ -151,30 +151,30 @@ var relocationTests = []relocationTest{
func TestDWARFRelocations(t *testing.T) { func TestDWARFRelocations(t *testing.T) {
for i, test := range relocationTests { for i, test := range relocationTests {
f, err := Open(test.file); f, err := Open(test.file)
if err != nil { if err != nil {
t.Error(err); t.Error(err)
continue; continue
} }
dwarf, err := f.DWARF(); dwarf, err := f.DWARF()
if err != nil { if err != nil {
t.Error(err); t.Error(err)
continue; continue
} }
reader := dwarf.Reader(); reader := dwarf.Reader()
// Checking only the first entry is sufficient since it has // Checking only the first entry is sufficient since it has
// many different strings. If the relocation had failed, all // many different strings. If the relocation had failed, all
// the string offsets would be zero and all the strings would // the string offsets would be zero and all the strings would
// end up being the same. // end up being the same.
firstEntry, err := reader.Next(); firstEntry, err := reader.Next()
if err != nil { if err != nil {
t.Error(err); t.Error(err)
continue; continue
} }
if !reflect.DeepEqual(test.firstEntry, firstEntry) { if !reflect.DeepEqual(test.firstEntry, firstEntry) {
t.Errorf("#%d: mismatch: got:%#v want:%#v", i, firstEntry, test.firstEntry); t.Errorf("#%d: mismatch: got:%#v want:%#v", i, firstEntry, test.firstEntry)
continue; continue
} }
} }
} }
...@@ -11,9 +11,9 @@ package gosym ...@@ -11,9 +11,9 @@ package gosym
import "encoding/binary" import "encoding/binary"
type LineTable struct { type LineTable struct {
Data []byte; Data []byte
PC uint64; PC uint64
Line int; Line int
} }
// TODO(rsc): Need to pull in quantum from architecture definition. // TODO(rsc): Need to pull in quantum from architecture definition.
...@@ -28,49 +28,49 @@ func (t *LineTable) parse(targetPC uint64, targetLine int) (b []byte, pc uint64, ...@@ -28,49 +28,49 @@ func (t *LineTable) parse(targetPC uint64, targetLine int) (b []byte, pc uint64,
// //
// Here we process each update individually, which simplifies // Here we process each update individually, which simplifies
// the code, but makes the corner cases more confusing. // the code, but makes the corner cases more confusing.
b, pc, line = t.Data, t.PC, t.Line; b, pc, line = t.Data, t.PC, t.Line
for pc <= targetPC && line != targetLine && len(b) > 0 { for pc <= targetPC && line != targetLine && len(b) > 0 {
code := b[0]; code := b[0]
b = b[1:]; b = b[1:]
switch { switch {
case code == 0: case code == 0:
if len(b) < 4 { if len(b) < 4 {
b = b[0:0]; b = b[0:0]
break; break
} }
val := binary.BigEndian.Uint32(b); val := binary.BigEndian.Uint32(b)
b = b[4:]; b = b[4:]
line += int(val); line += int(val)
case code <= 64: case code <= 64:
line += int(code) line += int(code)
case code <= 128: case code <= 128:
line -= int(code - 64) line -= int(code - 64)
default: default:
pc += quantum * uint64(code-128); pc += quantum * uint64(code-128)
continue; continue
} }
pc += quantum; pc += quantum
} }
return b, pc, line; return b, pc, line
} }
func (t *LineTable) slice(pc uint64) *LineTable { func (t *LineTable) slice(pc uint64) *LineTable {
data, pc, line := t.parse(pc, -1); data, pc, line := t.parse(pc, -1)
return &LineTable{data, pc, line}; return &LineTable{data, pc, line}
} }
func (t *LineTable) PCToLine(pc uint64) int { func (t *LineTable) PCToLine(pc uint64) int {
_, _, line := t.parse(pc, -1); _, _, line := t.parse(pc, -1)
return line; return line
} }
func (t *LineTable) LineToPC(line int, maxpc uint64) uint64 { func (t *LineTable) LineToPC(line int, maxpc uint64) uint64 {
_, pc, line1 := t.parse(maxpc, line); _, pc, line1 := t.parse(maxpc, line)
if line1 != line { if line1 != line {
return 0 return 0
} }
// Subtract quantum from PC to account for post-line increment // Subtract quantum from PC to account for post-line increment
return pc - quantum; return pc - quantum
} }
// NewLineTable returns a new PC/line table // NewLineTable returns a new PC/line table
......
...@@ -5,10 +5,10 @@ ...@@ -5,10 +5,10 @@
package gosym package gosym
import ( import (
"debug/elf"; "debug/elf"
"os"; "os"
"testing"; "testing"
"syscall"; "syscall"
) )
func dotest() bool { func dotest() bool {
...@@ -17,40 +17,40 @@ func dotest() bool { ...@@ -17,40 +17,40 @@ func dotest() bool {
} }
func getTable(t *testing.T) *Table { func getTable(t *testing.T) *Table {
f, tab := crack(os.Args[0], t); f, tab := crack(os.Args[0], t)
f.Close(); f.Close()
return tab; return tab
} }
func crack(file string, t *testing.T) (*elf.File, *Table) { func crack(file string, t *testing.T) (*elf.File, *Table) {
// Open self // Open self
f, err := elf.Open(file); f, err := elf.Open(file)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
return parse(file, f, t); return parse(file, f, t)
} }
func parse(file string, f *elf.File, t *testing.T) (*elf.File, *Table) { func parse(file string, f *elf.File, t *testing.T) (*elf.File, *Table) {
symdat, err := f.Section(".gosymtab").Data(); symdat, err := f.Section(".gosymtab").Data()
if err != nil { if err != nil {
f.Close(); f.Close()
t.Fatalf("reading %s gosymtab: %v", file, err); t.Fatalf("reading %s gosymtab: %v", file, err)
} }
pclndat, err := f.Section(".gopclntab").Data(); pclndat, err := f.Section(".gopclntab").Data()
if err != nil { if err != nil {
f.Close(); f.Close()
t.Fatalf("reading %s gopclntab: %v", file, err); t.Fatalf("reading %s gopclntab: %v", file, err)
} }
pcln := NewLineTable(pclndat, f.Section(".text").Addr); pcln := NewLineTable(pclndat, f.Section(".text").Addr)
tab, err := NewTable(symdat, pcln); tab, err := NewTable(symdat, pcln)
if err != nil { if err != nil {
f.Close(); f.Close()
t.Fatalf("parsing %s gosymtab: %v", file, err); t.Fatalf("parsing %s gosymtab: %v", file, err)
} }
return f, tab; return f, tab
} }
var goarch = os.Getenv("O") var goarch = os.Getenv("O")
...@@ -60,42 +60,42 @@ func TestLineFromAline(t *testing.T) { ...@@ -60,42 +60,42 @@ func TestLineFromAline(t *testing.T) {
return return
} }
tab := getTable(t); tab := getTable(t)
// Find the sym package // Find the sym package
pkg := tab.LookupFunc("gosym.TestLineFromAline").Obj; pkg := tab.LookupFunc("gosym.TestLineFromAline").Obj
if pkg == nil { if pkg == nil {
t.Fatalf("nil pkg") t.Fatalf("nil pkg")
} }
// Walk every absolute line and ensure that we hit every // Walk every absolute line and ensure that we hit every
// source line monotonically // source line monotonically
lastline := make(map[string]int); lastline := make(map[string]int)
final := -1; final := -1
for i := 0; i < 10000; i++ { for i := 0; i < 10000; i++ {
path, line := pkg.lineFromAline(i); path, line := pkg.lineFromAline(i)
// Check for end of object // Check for end of object
if path == "" { if path == "" {
if final == -1 { if final == -1 {
final = i - 1 final = i - 1
} }
continue; continue
} else if final != -1 { } else if final != -1 {
t.Fatalf("reached end of package at absolute line %d, but absolute line %d mapped to %s:%d", final, i, path, line) t.Fatalf("reached end of package at absolute line %d, but absolute line %d mapped to %s:%d", final, i, path, line)
} }
// It's okay to see files multiple times (e.g., sys.a) // It's okay to see files multiple times (e.g., sys.a)
if line == 1 { if line == 1 {
lastline[path] = 1; lastline[path] = 1
continue; continue
} }
// Check that the is the next line in path // Check that the is the next line in path
ll, ok := lastline[path]; ll, ok := lastline[path]
if !ok { if !ok {
t.Errorf("file %s starts on line %d", path, line) t.Errorf("file %s starts on line %d", path, line)
} else if line != ll+1 { } else if line != ll+1 {
t.Errorf("expected next line of file %s to be %d, got %d", path, ll+1, line) t.Errorf("expected next line of file %s to be %d, got %d", path, ll+1, line)
} }
lastline[path] = line; lastline[path] = line
} }
if final == -1 { if final == -1 {
t.Errorf("never reached end of object") t.Errorf("never reached end of object")
...@@ -107,15 +107,15 @@ func TestLineAline(t *testing.T) { ...@@ -107,15 +107,15 @@ func TestLineAline(t *testing.T) {
return return
} }
tab := getTable(t); tab := getTable(t)
for _, o := range tab.Files { for _, o := range tab.Files {
// A source file can appear multiple times in a // A source file can appear multiple times in a
// object. alineFromLine will always return alines in // object. alineFromLine will always return alines in
// the first file, so track which lines we've seen. // the first file, so track which lines we've seen.
found := make(map[string]int); found := make(map[string]int)
for i := 0; i < 1000; i++ { for i := 0; i < 1000; i++ {
path, line := o.lineFromAline(i); path, line := o.lineFromAline(i)
if path == "" { if path == "" {
break break
} }
...@@ -131,9 +131,9 @@ func TestLineAline(t *testing.T) { ...@@ -131,9 +131,9 @@ func TestLineAline(t *testing.T) {
continue continue
} }
} }
found[path] = line; found[path] = line
a, err := o.alineFromLine(path, line); a, err := o.alineFromLine(path, line)
if err != nil { if err != nil {
t.Errorf("absolute line %d in object %s maps to %s:%d, but mapping that back gives error %s", i, o.Paths[0].Name, path, line, err) t.Errorf("absolute line %d in object %s maps to %s:%d, but mapping that back gives error %s", i, o.Paths[0].Name, path, line, err)
} else if a != i { } else if a != i {
...@@ -151,20 +151,20 @@ func TestPCLine(t *testing.T) { ...@@ -151,20 +151,20 @@ func TestPCLine(t *testing.T) {
return return
} }
f, tab := crack("_test/pclinetest", t); f, tab := crack("_test/pclinetest", t)
text := f.Section(".text"); text := f.Section(".text")
textdat, err := text.Data(); textdat, err := text.Data()
if err != nil { if err != nil {
t.Fatalf("reading .text: %v", err) t.Fatalf("reading .text: %v", err)
} }
// Test PCToLine // Test PCToLine
sym := tab.LookupFunc("linefrompc"); sym := tab.LookupFunc("linefrompc")
wantLine := 0; wantLine := 0
for pc := sym.Entry; pc < sym.End; pc++ { for pc := sym.Entry; pc < sym.End; pc++ {
file, line, fn := tab.PCToLine(pc); file, line, fn := tab.PCToLine(pc)
off := pc - text.Addr; // TODO(rsc): should not need off; bug in 8g off := pc - text.Addr // TODO(rsc): should not need off; bug in 8g
wantLine += int(textdat[off]); wantLine += int(textdat[off])
if fn == nil { if fn == nil {
t.Errorf("failed to get line of PC %#x", pc) t.Errorf("failed to get line of PC %#x", pc)
} else if len(file) < 12 || file[len(file)-12:] != "pclinetest.s" || line != wantLine || fn != sym { } else if len(file) < 12 || file[len(file)-12:] != "pclinetest.s" || line != wantLine || fn != sym {
...@@ -173,24 +173,24 @@ func TestPCLine(t *testing.T) { ...@@ -173,24 +173,24 @@ func TestPCLine(t *testing.T) {
} }
// Test LineToPC // Test LineToPC
sym = tab.LookupFunc("pcfromline"); sym = tab.LookupFunc("pcfromline")
lookupline := -1; lookupline := -1
wantLine = 0; wantLine = 0
off := uint64(0); // TODO(rsc): should not need off; bug in 8g off := uint64(0) // TODO(rsc): should not need off; bug in 8g
for pc := sym.Value; pc < sym.End; pc += 2 + uint64(textdat[off]) { for pc := sym.Value; pc < sym.End; pc += 2 + uint64(textdat[off]) {
file, line, fn := tab.PCToLine(pc); file, line, fn := tab.PCToLine(pc)
off = pc - text.Addr; off = pc - text.Addr
wantLine += int(textdat[off]); wantLine += int(textdat[off])
if line != wantLine { if line != wantLine {
t.Errorf("expected line %d at PC %#x in pcfromline, got %d", wantLine, pc, line); t.Errorf("expected line %d at PC %#x in pcfromline, got %d", wantLine, pc, line)
off = pc + 1 - text.Addr; off = pc + 1 - text.Addr
continue; continue
} }
if lookupline == -1 { if lookupline == -1 {
lookupline = line lookupline = line
} }
for ; lookupline <= line; lookupline++ { for ; lookupline <= line; lookupline++ {
pc2, fn2, err := tab.LineToPC(file, lookupline); pc2, fn2, err := tab.LineToPC(file, lookupline)
if lookupline != line { if lookupline != line {
// Should be nothing on this line // Should be nothing on this line
if err == nil { if err == nil {
...@@ -202,6 +202,6 @@ func TestPCLine(t *testing.T) { ...@@ -202,6 +202,6 @@ func TestPCLine(t *testing.T) {
t.Errorf("expected PC %#x (%s) at line %d, got PC %#x (%s)", pc, fn.Name, line, pc2, fn2.Name) t.Errorf("expected PC %#x (%s) at line %d, got PC %#x (%s)", pc, fn.Name, line, pc2, fn2.Name)
} }
} }
off = pc + 1 - text.Addr; off = pc + 1 - text.Addr
} }
} }
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment