]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
debug/dwarf: Support DWARF versions 3 and 4.
authorIan Lance Taylor <ian@gcc.gnu.org>
Fri, 9 Mar 2012 06:35:00 +0000 (06:35 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Fri, 9 Mar 2012 06:35:00 +0000 (06:35 +0000)
From-SVN: r185126

libgo/go/debug/dwarf/buf.go
libgo/go/debug/dwarf/const.go
libgo/go/debug/dwarf/entry.go
libgo/go/debug/dwarf/line.go
libgo/go/debug/dwarf/open.go
libgo/go/debug/dwarf/type.go
libgo/go/debug/dwarf/unit.go

index 6dc28d2568c39ba5dac17eb2bb1387e1b6844168..08e37be4b38399623f900b20e8d14e5e7ffca1bd 100644 (file)
@@ -13,17 +13,17 @@ import (
 
 // Data buffer being decoded.
 type buf struct {
-       dwarf    *Data
-       order    binary.ByteOrder
-       name     string
-       off      Offset
-       data     []byte
-       addrsize int
-       err      error
+       dwarf *Data
+       u     *unit
+       order binary.ByteOrder
+       name  string
+       off   Offset
+       data  []byte
+       err   error
 }
 
-func makeBuf(d *Data, name string, off Offset, data []byte, addrsize int) buf {
-       return buf{d, d.order, name, off, data, addrsize, nil}
+func makeBuf(d *Data, u *unit, name string, off Offset, data []byte) buf {
+       return buf{d, u, d.order, name, off, data, nil}
 }
 
 func (b *buf) uint8() uint8 {
@@ -121,15 +121,17 @@ func (b *buf) int() int64 {
 
 // Address-sized uint.
 func (b *buf) addr() uint64 {
-       switch b.addrsize {
-       case 1:
-               return uint64(b.uint8())
-       case 2:
-               return uint64(b.uint16())
-       case 4:
-               return uint64(b.uint32())
-       case 8:
-               return uint64(b.uint64())
+       if b.u != nil {
+               switch b.u.addrsize {
+               case 1:
+                       return uint64(b.uint8())
+               case 2:
+                       return uint64(b.uint16())
+               case 4:
+                       return uint64(b.uint32())
+               case 8:
+                       return uint64(b.uint64())
+               }
        }
        b.error("unknown address size")
        return 0
index 5301edc461ad98b3d9799827cfa3ced542161b02..ebe9a71a0c5d294f827026d91523c280f9ec53f1 100644 (file)
@@ -207,6 +207,11 @@ const (
        formRef8        format = 0x14
        formRefUdata    format = 0x15
        formIndirect    format = 0x16
+       // following are defined in DWARF 4
+       formSecOffset   format = 0x17
+       formExprLoc     format = 0x18
+       formFlagPresent format = 0x19
+       formRefSig8     format = 0x20
 )
 
 // A Tag is the classification (the type) of an Entry.
index f9a4c1b4119744fd1fc746c074be5e87b68a4dc9..4761d74cd799572e079c5defe23db9c008546814 100644 (file)
@@ -40,7 +40,7 @@ func (d *Data) parseAbbrev(off uint32) (abbrevTable, error) {
        } else {
                data = data[off:]
        }
-       b := makeBuf(d, "abbrev", 0, data, 0)
+       b := makeBuf(d, nil, "abbrev", 0, data)
 
        // Error handling is simplified by the buf getters
        // returning an endless stream of 0s after an error.
@@ -182,13 +182,37 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry {
                case formUdata:
                        val = int64(b.uint())
 
+               // exprloc
+               case formExprLoc:
+                       val = b.bytes(int(b.uint()))
+
                // flag
                case formFlag:
                        val = b.uint8() == 1
+               case formFlagPresent:
+                       val = true
+
+               // lineptr, loclistptr, macptr, rangelistptr
+               case formSecOffset:
+                       if b.u == nil {
+                               b.error("unknown size for DW_FORM_sec_offset")
+                       } else if b.u.dwarf64 {
+                               val = Offset(b.uint64())
+                       } else {
+                               val = Offset(b.uint32())
+                       }
 
                // reference to other entry
                case formRefAddr:
-                       val = Offset(b.addr())
+                       if b.u == nil {
+                               b.error("unknown version for DW_FORM_ref_addr")
+                       } else if b.u.version == 2 {
+                               val = Offset(b.addr())
+                       } else if b.u.dwarf64 {
+                               val = Offset(b.uint64())
+                       } else {
+                               val = Offset(b.uint32())
+                       }
                case formRef1:
                        val = Offset(b.uint8()) + ubase
                case formRef2:
@@ -199,6 +223,8 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry {
                        val = Offset(b.uint64()) + ubase
                case formRefUdata:
                        val = Offset(b.uint()) + ubase
+               case formRefSig8:
+                       val = b.uint64()
 
                // string
                case formString:
@@ -208,7 +234,7 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry {
                        if b.err != nil {
                                return nil
                        }
-                       b1 := makeBuf(b.dwarf, "str", 0, b.dwarf.str, 0)
+                       b1 := makeBuf(b.dwarf, b.u, "str", 0, b.dwarf.str)
                        b1.skip(int(off))
                        val = b1.string()
                        if b1.err != nil {
@@ -251,7 +277,7 @@ func (d *Data) unitReader(i int) *Reader {
        r := &Reader{d: d}
        r.unit = i
        u := &d.unit[i]
-       r.b = makeBuf(d, "info", u.off, u.data, u.addrsize)
+       r.b = makeBuf(d, u, "info", u.off, u.data)
        return r
 }
 
@@ -267,7 +293,7 @@ func (r *Reader) Seek(off Offset) {
                }
                u := &d.unit[0]
                r.unit = 0
-               r.b = makeBuf(r.d, "info", u.off, u.data, u.addrsize)
+               r.b = makeBuf(r.d, u, "info", u.off, u.data)
                return
        }
 
@@ -278,7 +304,7 @@ func (r *Reader) Seek(off Offset) {
                u = &d.unit[i]
                if u.off <= off && off < u.off+Offset(len(u.data)) {
                        r.unit = i
-                       r.b = makeBuf(r.d, "info", off, u.data[off-u.off:], u.addrsize)
+                       r.b = makeBuf(r.d, u, "info", off, u.data[off-u.off:])
                        return
                }
        }
@@ -290,7 +316,7 @@ func (r *Reader) maybeNextUnit() {
        for len(r.b.data) == 0 && r.unit+1 < len(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, u, "info", u.off, u.data)
        }
 }
 
index 091ebe0d17d675365044b2d56de5a8711ccf7737..f9c77cc87e46e67772f5e17e174e83fde58e3dd9 100644 (file)
@@ -74,9 +74,17 @@ func (d *Data) readUnitLine(i int, u *unit) error {
                                // TODO: Handle AttrRanges and .debug_ranges.
                                _ = f
                        }
-                       if off, ok := e.Val(AttrStmtList).(int64); ok {
-                               u.lineoff = Offset(off)
-                               setLineOff = true
+                       val := e.Val(AttrStmtList)
+                       if val != nil {
+                               if off, ok := val.(int64); ok {
+                                       u.lineoff = Offset(off)
+                                       setLineOff = true
+                               } else if off, ok := val.(Offset); ok {
+                                       u.lineoff = off
+                                       setLineOff = true
+                               } else {
+                                       return errors.New("unrecognized format for DW_ATTR_stmt_list")
+                               }
                        }
                        if dir, ok := e.Val(AttrCompDir).(string); ok {
                                u.dir = dir
@@ -177,15 +185,15 @@ func (d *Data) parseLine(u *unit) error {
        if u.lineoff+1 == 0 {
                return errors.New("unknown line offset")
        }
-       b := makeBuf(d, "line", u.lineoff, d.line, u.addrsize)
+       b := makeBuf(d, u, "line", u.lineoff, d.line[u.lineoff:])
        len := uint64(b.uint32())
-       offSize := 4
+       dwarf64 := false
        if len == 0xffffffff {
                len = b.uint64()
-               offSize = 8
+               dwarf64 = true
        }
        end := b.off + Offset(len)
-       hdr := d.parseLineHdr(u, &b, offSize)
+       hdr := d.parseLineHdr(u, &b, dwarf64)
        if b.err == nil {
                d.parseLineProgram(u, &b, hdr, end)
        }
@@ -193,14 +201,20 @@ func (d *Data) parseLine(u *unit) error {
 }
 
 // parseLineHdr parses a line number program header.
-func (d *Data) parseLineHdr(u *unit, b *buf, offSize int) (hdr lineHdr) {
+func (d *Data) parseLineHdr(u *unit, b *buf, dwarf64 bool) (hdr lineHdr) {
        hdr.version = b.uint16()
        if hdr.version < 2 || hdr.version > 4 {
                b.error("unsupported DWARF version " + strconv.Itoa(int(hdr.version)))
                return
        }
 
-       b.bytes(offSize) // header length
+       var hlen Offset
+       if dwarf64 {
+               hlen = Offset(b.uint64())
+       } else {
+               hlen = Offset(b.uint32())
+       }
+       end := b.off + hlen
 
        hdr.minInsnLen = b.uint8()
        if hdr.version < 4 {
@@ -241,6 +255,10 @@ func (d *Data) parseLineHdr(u *unit, b *buf, offSize int) (hdr lineHdr) {
                hdr.files = append(hdr.files, f)
        }
 
+       if end > b.off {
+               b.bytes(int(end - b.off))
+       }
+
        return
 }
 
@@ -296,6 +314,7 @@ func (d *Data) parseLineProgram(u *unit, b *buf, hdr lineHdr, end Offset) {
                                u.lines = append(u.lines, lines...)
                                lineInfo = resetLineInfo
                                lines = nil
+                               newLineInfo = true
                        case LineExtSetAddress:
                                address = b.addr()
                        case LineExtDefineFile:
index 37a518b6d376969e5371b88f72aad1779e4957f7..75798925296cff7375db930854e61f24ee67ae6c 100644 (file)
@@ -24,7 +24,6 @@ type Data struct {
 
        // parsed data
        abbrevCache map[uint32]abbrevTable
-       addrsize    int
        order       binary.ByteOrder
        typeCache   map[Offset]Type
        unit        []unit
index 4502355022d60aafa499b1ac9ee6a1fd7b090cf1..2ef8ca01bf83e2aa6875d1bfb90e316b13c42d0b 100644 (file)
@@ -435,7 +435,7 @@ func (d *Data) Type(off Offset) (Type, error) {
                                        goto Error
                                }
                                if loc, ok := kid.Val(AttrDataMemberLoc).([]byte); ok {
-                                       b := makeBuf(d, "location", 0, loc, d.addrsize)
+                                       b := makeBuf(d, nil, "location", 0, loc)
                                        if b.uint8() != opPlusUconst {
                                                err = DecodeError{"info", kid.Offset, "unexpected opcode"}
                                                goto Error
index 931468a3718e22464e828a0d8f6a8554364635a8..b1903208715b913e7010c5a10614558d4a92fac5 100644 (file)
@@ -16,6 +16,8 @@ type unit struct {
        data     []byte
        atable   abbrevTable
        addrsize int
+       version  int
+       dwarf64  bool // True for 64-bit DWARF format
        dir      string
        pc       []addrRange   // PC ranges in this compilation unit
        lines    []mapLineInfo // PC -> line mapping
@@ -30,9 +32,18 @@ type addrRange struct {
 func (d *Data) parseUnits() ([]unit, error) {
        // Count units.
        nunit := 0
-       b := makeBuf(d, "info", 0, d.info, 0)
+       b := makeBuf(d, nil, "info", 0, d.info)
        for len(b.data) > 0 {
-               b.skip(int(b.uint32()))
+               len := b.uint32()
+               if len == 0xffffffff {
+                       len64 := b.uint64()
+                       if len64 != uint64(int(len64)) {
+                               b.error("unit length overflow")
+                               break
+                       }
+                       len = uint32(len64)
+               }
+               b.skip(int(len))
                nunit++
        }
        if b.err != nil {
@@ -40,13 +51,18 @@ func (d *Data) parseUnits() ([]unit, error) {
        }
 
        // Again, this time writing them down.
-       b = makeBuf(d, "info", 0, d.info, 0)
+       b = makeBuf(d, nil, "info", 0, d.info)
        units := make([]unit, nunit)
        for i := range units {
                u := &units[i]
                u.base = b.off
                n := b.uint32()
-               if vers := b.uint16(); vers != 2 {
+               if n == 0xffffffff {
+                       u.dwarf64 = true
+                       n = uint32(b.uint64())
+               }
+               vers := b.uint16()
+               if vers < 2 || vers > 4 {
                        b.error("unsupported DWARF version " + strconv.Itoa(int(vers)))
                        break
                }
@@ -57,6 +73,7 @@ func (d *Data) parseUnits() ([]unit, error) {
                        }
                        break
                }
+               u.version = int(vers)
                u.atable = atable
                u.addrsize = int(b.uint8())
                u.off = b.off