1// Copyright 2019 Google LLC 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package dwarf 16 17import "strconv" 18 19// DWARF debug info is split into a sequence of compilation units. 20// Each unit has its own abbreviation table and address size. 21 22type unit struct { 23 base Offset // byte offset of header within the aggregate info 24 off Offset // byte offset of data within the aggregate info 25 data []byte 26 atable abbrevTable 27 asize int 28 vers int 29 is64 bool // True for 64-bit DWARF format 30} 31 32// Implement the dataFormat interface. 33 34func (u *unit) version() int { 35 return u.vers 36} 37 38func (u *unit) dwarf64() (bool, bool) { 39 return u.is64, true 40} 41 42func (u *unit) addrsize() int { 43 return u.asize 44} 45 46func (d *Data) parseUnits() ([]unit, error) { 47 // Count units. 48 nunit := 0 49 b := makeBuf(d, unknownFormat{}, "info", 0, d.info) 50 for len(b.data) > 0 { 51 len := b.uint32() 52 if len == 0xffffffff { 53 len64 := b.uint64() 54 if len64 != uint64(uint32(len64)) { 55 b.error("unit length overflow") 56 break 57 } 58 len = uint32(len64) 59 } 60 b.skip(int(len)) 61 nunit++ 62 } 63 if b.err != nil { 64 return nil, b.err 65 } 66 67 // Again, this time writing them down. 68 b = makeBuf(d, unknownFormat{}, "info", 0, d.info) 69 units := make([]unit, nunit) 70 for i := range units { 71 u := &units[i] 72 u.base = b.off 73 n := b.uint32() 74 if n == 0xffffffff { 75 u.is64 = true 76 n = uint32(b.uint64()) 77 } 78 vers := b.uint16() 79 if vers != 2 && vers != 3 && vers != 4 { 80 b.error("unsupported DWARF version " + strconv.Itoa(int(vers))) 81 break 82 } 83 u.vers = int(vers) 84 atable, err := d.parseAbbrev(b.uint32()) 85 if err != nil { 86 if b.err == nil { 87 b.err = err 88 } 89 break 90 } 91 u.atable = atable 92 u.asize = int(b.uint8()) 93 u.off = b.off 94 u.data = b.bytes(int(n - (2 + 4 + 1))) 95 } 96 if b.err != nil { 97 return nil, b.err 98 } 99 return units, nil 100} 101