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