podman

Форк
0
1650 строк · 42.9 Кб
1
// Copyright 2016 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4

5
// Package dwarf generates DWARF debugging information.
6
// DWARF generation is split between the compiler and the linker,
7
// this package contains the shared code.
8
package dwarf
9

10
import (
11
	"bytes"
12
	"github.com/twitchyliquid64/golang-asm/objabi"
13
	"errors"
14
	"fmt"
15
	"os/exec"
16
	"sort"
17
	"strconv"
18
	"strings"
19
)
20

21
// InfoPrefix is the prefix for all the symbols containing DWARF info entries.
22
const InfoPrefix = "go.info."
23

24
// ConstInfoPrefix is the prefix for all symbols containing DWARF info
25
// entries that contain constants.
26
const ConstInfoPrefix = "go.constinfo."
27

28
// CUInfoPrefix is the prefix for symbols containing information to
29
// populate the DWARF compilation unit info entries.
30
const CUInfoPrefix = "go.cuinfo."
31

32
// Used to form the symbol name assigned to the DWARF 'abstract subprogram"
33
// info entry for a function
34
const AbstractFuncSuffix = "$abstract"
35

36
// Controls logging/debugging for selected aspects of DWARF subprogram
37
// generation (functions, scopes).
38
var logDwarf bool
39

40
// Sym represents a symbol.
41
type Sym interface {
42
	Length(dwarfContext interface{}) int64
43
}
44

45
// A Var represents a local variable or a function parameter.
46
type Var struct {
47
	Name          string
48
	Abbrev        int // Either DW_ABRV_AUTO[_LOCLIST] or DW_ABRV_PARAM[_LOCLIST]
49
	IsReturnValue bool
50
	IsInlFormal   bool
51
	StackOffset   int32
52
	// This package can't use the ssa package, so it can't mention ssa.FuncDebug,
53
	// so indirect through a closure.
54
	PutLocationList func(listSym, startPC Sym)
55
	Scope           int32
56
	Type            Sym
57
	DeclFile        string
58
	DeclLine        uint
59
	DeclCol         uint
60
	InlIndex        int32 // subtract 1 to form real index into InlTree
61
	ChildIndex      int32 // child DIE index in abstract function
62
	IsInAbstract    bool  // variable exists in abstract function
63
}
64

65
// A Scope represents a lexical scope. All variables declared within a
66
// scope will only be visible to instructions covered by the scope.
67
// Lexical scopes are contiguous in source files but can end up being
68
// compiled to discontiguous blocks of instructions in the executable.
69
// The Ranges field lists all the blocks of instructions that belong
70
// in this scope.
71
type Scope struct {
72
	Parent int32
73
	Ranges []Range
74
	Vars   []*Var
75
}
76

77
// A Range represents a half-open interval [Start, End).
78
type Range struct {
79
	Start, End int64
80
}
81

82
// This container is used by the PutFunc* variants below when
83
// creating the DWARF subprogram DIE(s) for a function.
84
type FnState struct {
85
	Name          string
86
	Importpath    string
87
	Info          Sym
88
	Filesym       Sym
89
	Loc           Sym
90
	Ranges        Sym
91
	Absfn         Sym
92
	StartPC       Sym
93
	Size          int64
94
	External      bool
95
	Scopes        []Scope
96
	InlCalls      InlCalls
97
	UseBASEntries bool
98
}
99

100
func EnableLogging(doit bool) {
101
	logDwarf = doit
102
}
103

104
// UnifyRanges merges the list of ranges of c into the list of ranges of s
105
func (s *Scope) UnifyRanges(c *Scope) {
106
	out := make([]Range, 0, len(s.Ranges)+len(c.Ranges))
107

108
	i, j := 0, 0
109
	for {
110
		var cur Range
111
		if i < len(s.Ranges) && j < len(c.Ranges) {
112
			if s.Ranges[i].Start < c.Ranges[j].Start {
113
				cur = s.Ranges[i]
114
				i++
115
			} else {
116
				cur = c.Ranges[j]
117
				j++
118
			}
119
		} else if i < len(s.Ranges) {
120
			cur = s.Ranges[i]
121
			i++
122
		} else if j < len(c.Ranges) {
123
			cur = c.Ranges[j]
124
			j++
125
		} else {
126
			break
127
		}
128

129
		if n := len(out); n > 0 && cur.Start <= out[n-1].End {
130
			out[n-1].End = cur.End
131
		} else {
132
			out = append(out, cur)
133
		}
134
	}
135

136
	s.Ranges = out
137
}
138

139
// AppendRange adds r to s, if r is non-empty.
140
// If possible, it extends the last Range in s.Ranges; if not, it creates a new one.
141
func (s *Scope) AppendRange(r Range) {
142
	if r.End <= r.Start {
143
		return
144
	}
145
	i := len(s.Ranges)
146
	if i > 0 && s.Ranges[i-1].End == r.Start {
147
		s.Ranges[i-1].End = r.End
148
		return
149
	}
150
	s.Ranges = append(s.Ranges, r)
151
}
152

153
type InlCalls struct {
154
	Calls []InlCall
155
}
156

157
type InlCall struct {
158
	// index into ctx.InlTree describing the call inlined here
159
	InlIndex int
160

161
	// Symbol of file containing inlined call site (really *obj.LSym).
162
	CallFile Sym
163

164
	// Line number of inlined call site.
165
	CallLine uint32
166

167
	// Dwarf abstract subroutine symbol (really *obj.LSym).
168
	AbsFunSym Sym
169

170
	// Indices of child inlines within Calls array above.
171
	Children []int
172

173
	// entries in this list are PAUTO's created by the inliner to
174
	// capture the promoted formals and locals of the inlined callee.
175
	InlVars []*Var
176

177
	// PC ranges for this inlined call.
178
	Ranges []Range
179

180
	// Root call (not a child of some other call).
181
	Root bool
182
}
183

184
// A Context specifies how to add data to a Sym.
185
type Context interface {
186
	PtrSize() int
187
	AddInt(s Sym, size int, i int64)
188
	AddBytes(s Sym, b []byte)
189
	AddAddress(s Sym, t interface{}, ofs int64)
190
	AddCURelativeAddress(s Sym, t interface{}, ofs int64)
191
	AddSectionOffset(s Sym, size int, t interface{}, ofs int64)
192
	AddDWARFAddrSectionOffset(s Sym, t interface{}, ofs int64)
193
	CurrentOffset(s Sym) int64
194
	RecordDclReference(from Sym, to Sym, dclIdx int, inlIndex int)
195
	RecordChildDieOffsets(s Sym, vars []*Var, offsets []int32)
196
	AddString(s Sym, v string)
197
	AddFileRef(s Sym, f interface{})
198
	Logf(format string, args ...interface{})
199
}
200

201
// AppendUleb128 appends v to b using DWARF's unsigned LEB128 encoding.
202
func AppendUleb128(b []byte, v uint64) []byte {
203
	for {
204
		c := uint8(v & 0x7f)
205
		v >>= 7
206
		if v != 0 {
207
			c |= 0x80
208
		}
209
		b = append(b, c)
210
		if c&0x80 == 0 {
211
			break
212
		}
213
	}
214
	return b
215
}
216

217
// AppendSleb128 appends v to b using DWARF's signed LEB128 encoding.
218
func AppendSleb128(b []byte, v int64) []byte {
219
	for {
220
		c := uint8(v & 0x7f)
221
		s := uint8(v & 0x40)
222
		v >>= 7
223
		if (v != -1 || s == 0) && (v != 0 || s != 0) {
224
			c |= 0x80
225
		}
226
		b = append(b, c)
227
		if c&0x80 == 0 {
228
			break
229
		}
230
	}
231
	return b
232
}
233

234
// sevenbits contains all unsigned seven bit numbers, indexed by their value.
235
var sevenbits = [...]byte{
236
	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
237
	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
238
	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
239
	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
240
	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
241
	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
242
	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
243
	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
244
}
245

246
// sevenBitU returns the unsigned LEB128 encoding of v if v is seven bits and nil otherwise.
247
// The contents of the returned slice must not be modified.
248
func sevenBitU(v int64) []byte {
249
	if uint64(v) < uint64(len(sevenbits)) {
250
		return sevenbits[v : v+1]
251
	}
252
	return nil
253
}
254

255
// sevenBitS returns the signed LEB128 encoding of v if v is seven bits and nil otherwise.
256
// The contents of the returned slice must not be modified.
257
func sevenBitS(v int64) []byte {
258
	if uint64(v) <= 63 {
259
		return sevenbits[v : v+1]
260
	}
261
	if uint64(-v) <= 64 {
262
		return sevenbits[128+v : 128+v+1]
263
	}
264
	return nil
265
}
266

267
// Uleb128put appends v to s using DWARF's unsigned LEB128 encoding.
268
func Uleb128put(ctxt Context, s Sym, v int64) {
269
	b := sevenBitU(v)
270
	if b == nil {
271
		var encbuf [20]byte
272
		b = AppendUleb128(encbuf[:0], uint64(v))
273
	}
274
	ctxt.AddBytes(s, b)
275
}
276

277
// Sleb128put appends v to s using DWARF's signed LEB128 encoding.
278
func Sleb128put(ctxt Context, s Sym, v int64) {
279
	b := sevenBitS(v)
280
	if b == nil {
281
		var encbuf [20]byte
282
		b = AppendSleb128(encbuf[:0], v)
283
	}
284
	ctxt.AddBytes(s, b)
285
}
286

287
/*
288
 * Defining Abbrevs. This is hardcoded on a per-platform basis (that is,
289
 * each platform will see a fixed abbrev table for all objects); the number
290
 * of abbrev entries is fairly small (compared to C++ objects).  The DWARF
291
 * spec places no restriction on the ordering of attributes in the
292
 * Abbrevs and DIEs, and we will always write them out in the order
293
 * of declaration in the abbrev.
294
 */
295
type dwAttrForm struct {
296
	attr uint16
297
	form uint8
298
}
299

300
// Go-specific type attributes.
301
const (
302
	DW_AT_go_kind = 0x2900
303
	DW_AT_go_key  = 0x2901
304
	DW_AT_go_elem = 0x2902
305
	// Attribute for DW_TAG_member of a struct type.
306
	// Nonzero value indicates the struct field is an embedded field.
307
	DW_AT_go_embedded_field = 0x2903
308
	DW_AT_go_runtime_type   = 0x2904
309

310
	DW_AT_go_package_name = 0x2905 // Attribute for DW_TAG_compile_unit
311

312
	DW_AT_internal_location = 253 // params and locals; not emitted
313
)
314

315
// Index into the abbrevs table below.
316
// Keep in sync with ispubname() and ispubtype() in ld/dwarf.go.
317
// ispubtype considers >= NULLTYPE public
318
const (
319
	DW_ABRV_NULL = iota
320
	DW_ABRV_COMPUNIT
321
	DW_ABRV_COMPUNIT_TEXTLESS
322
	DW_ABRV_FUNCTION
323
	DW_ABRV_FUNCTION_ABSTRACT
324
	DW_ABRV_FUNCTION_CONCRETE
325
	DW_ABRV_INLINED_SUBROUTINE
326
	DW_ABRV_INLINED_SUBROUTINE_RANGES
327
	DW_ABRV_VARIABLE
328
	DW_ABRV_INT_CONSTANT
329
	DW_ABRV_AUTO
330
	DW_ABRV_AUTO_LOCLIST
331
	DW_ABRV_AUTO_ABSTRACT
332
	DW_ABRV_AUTO_CONCRETE
333
	DW_ABRV_AUTO_CONCRETE_LOCLIST
334
	DW_ABRV_PARAM
335
	DW_ABRV_PARAM_LOCLIST
336
	DW_ABRV_PARAM_ABSTRACT
337
	DW_ABRV_PARAM_CONCRETE
338
	DW_ABRV_PARAM_CONCRETE_LOCLIST
339
	DW_ABRV_LEXICAL_BLOCK_RANGES
340
	DW_ABRV_LEXICAL_BLOCK_SIMPLE
341
	DW_ABRV_STRUCTFIELD
342
	DW_ABRV_FUNCTYPEPARAM
343
	DW_ABRV_DOTDOTDOT
344
	DW_ABRV_ARRAYRANGE
345
	DW_ABRV_NULLTYPE
346
	DW_ABRV_BASETYPE
347
	DW_ABRV_ARRAYTYPE
348
	DW_ABRV_CHANTYPE
349
	DW_ABRV_FUNCTYPE
350
	DW_ABRV_IFACETYPE
351
	DW_ABRV_MAPTYPE
352
	DW_ABRV_PTRTYPE
353
	DW_ABRV_BARE_PTRTYPE // only for void*, no DW_AT_type attr to please gdb 6.
354
	DW_ABRV_SLICETYPE
355
	DW_ABRV_STRINGTYPE
356
	DW_ABRV_STRUCTTYPE
357
	DW_ABRV_TYPEDECL
358
	DW_NABRV
359
)
360

361
type dwAbbrev struct {
362
	tag      uint8
363
	children uint8
364
	attr     []dwAttrForm
365
}
366

367
var abbrevsFinalized bool
368

369
// expandPseudoForm takes an input DW_FORM_xxx value and translates it
370
// into a platform-appropriate concrete form. Existing concrete/real
371
// DW_FORM values are left untouched. For the moment the only
372
// pseudo-form is DW_FORM_udata_pseudo, which gets expanded to
373
// DW_FORM_data4 on Darwin and DW_FORM_udata everywhere else. See
374
// issue #31459 for more context.
375
func expandPseudoForm(form uint8) uint8 {
376
	// Is this a pseudo-form?
377
	if form != DW_FORM_udata_pseudo {
378
		return form
379
	}
380
	expandedForm := DW_FORM_udata
381
	if objabi.GOOS == "darwin" {
382
		expandedForm = DW_FORM_data4
383
	}
384
	return uint8(expandedForm)
385
}
386

387
// Abbrevs() returns the finalized abbrev array for the platform,
388
// expanding any DW_FORM pseudo-ops to real values.
389
func Abbrevs() []dwAbbrev {
390
	if abbrevsFinalized {
391
		return abbrevs[:]
392
	}
393
	for i := 1; i < DW_NABRV; i++ {
394
		for j := 0; j < len(abbrevs[i].attr); j++ {
395
			abbrevs[i].attr[j].form = expandPseudoForm(abbrevs[i].attr[j].form)
396
		}
397
	}
398
	abbrevsFinalized = true
399
	return abbrevs[:]
400
}
401

402
// abbrevs is a raw table of abbrev entries; it needs to be post-processed
403
// by the Abbrevs() function above prior to being consumed, to expand
404
// the 'pseudo-form' entries below to real DWARF form values.
405

406
var abbrevs = [DW_NABRV]dwAbbrev{
407
	/* The mandatory DW_ABRV_NULL entry. */
408
	{0, 0, []dwAttrForm{}},
409

410
	/* COMPUNIT */
411
	{
412
		DW_TAG_compile_unit,
413
		DW_CHILDREN_yes,
414
		[]dwAttrForm{
415
			{DW_AT_name, DW_FORM_string},
416
			{DW_AT_language, DW_FORM_data1},
417
			{DW_AT_stmt_list, DW_FORM_sec_offset},
418
			{DW_AT_low_pc, DW_FORM_addr},
419
			{DW_AT_ranges, DW_FORM_sec_offset},
420
			{DW_AT_comp_dir, DW_FORM_string},
421
			{DW_AT_producer, DW_FORM_string},
422
			{DW_AT_go_package_name, DW_FORM_string},
423
		},
424
	},
425

426
	/* COMPUNIT_TEXTLESS */
427
	{
428
		DW_TAG_compile_unit,
429
		DW_CHILDREN_yes,
430
		[]dwAttrForm{
431
			{DW_AT_name, DW_FORM_string},
432
			{DW_AT_language, DW_FORM_data1},
433
			{DW_AT_comp_dir, DW_FORM_string},
434
			{DW_AT_producer, DW_FORM_string},
435
			{DW_AT_go_package_name, DW_FORM_string},
436
		},
437
	},
438

439
	/* FUNCTION */
440
	{
441
		DW_TAG_subprogram,
442
		DW_CHILDREN_yes,
443
		[]dwAttrForm{
444
			{DW_AT_name, DW_FORM_string},
445
			{DW_AT_low_pc, DW_FORM_addr},
446
			{DW_AT_high_pc, DW_FORM_addr},
447
			{DW_AT_frame_base, DW_FORM_block1},
448
			{DW_AT_decl_file, DW_FORM_data4},
449
			{DW_AT_external, DW_FORM_flag},
450
		},
451
	},
452

453
	/* FUNCTION_ABSTRACT */
454
	{
455
		DW_TAG_subprogram,
456
		DW_CHILDREN_yes,
457
		[]dwAttrForm{
458
			{DW_AT_name, DW_FORM_string},
459
			{DW_AT_inline, DW_FORM_data1},
460
			{DW_AT_external, DW_FORM_flag},
461
		},
462
	},
463

464
	/* FUNCTION_CONCRETE */
465
	{
466
		DW_TAG_subprogram,
467
		DW_CHILDREN_yes,
468
		[]dwAttrForm{
469
			{DW_AT_abstract_origin, DW_FORM_ref_addr},
470
			{DW_AT_low_pc, DW_FORM_addr},
471
			{DW_AT_high_pc, DW_FORM_addr},
472
			{DW_AT_frame_base, DW_FORM_block1},
473
		},
474
	},
475

476
	/* INLINED_SUBROUTINE */
477
	{
478
		DW_TAG_inlined_subroutine,
479
		DW_CHILDREN_yes,
480
		[]dwAttrForm{
481
			{DW_AT_abstract_origin, DW_FORM_ref_addr},
482
			{DW_AT_low_pc, DW_FORM_addr},
483
			{DW_AT_high_pc, DW_FORM_addr},
484
			{DW_AT_call_file, DW_FORM_data4},
485
			{DW_AT_call_line, DW_FORM_udata_pseudo}, // pseudo-form
486
		},
487
	},
488

489
	/* INLINED_SUBROUTINE_RANGES */
490
	{
491
		DW_TAG_inlined_subroutine,
492
		DW_CHILDREN_yes,
493
		[]dwAttrForm{
494
			{DW_AT_abstract_origin, DW_FORM_ref_addr},
495
			{DW_AT_ranges, DW_FORM_sec_offset},
496
			{DW_AT_call_file, DW_FORM_data4},
497
			{DW_AT_call_line, DW_FORM_udata_pseudo}, // pseudo-form
498
		},
499
	},
500

501
	/* VARIABLE */
502
	{
503
		DW_TAG_variable,
504
		DW_CHILDREN_no,
505
		[]dwAttrForm{
506
			{DW_AT_name, DW_FORM_string},
507
			{DW_AT_location, DW_FORM_block1},
508
			{DW_AT_type, DW_FORM_ref_addr},
509
			{DW_AT_external, DW_FORM_flag},
510
		},
511
	},
512

513
	/* INT CONSTANT */
514
	{
515
		DW_TAG_constant,
516
		DW_CHILDREN_no,
517
		[]dwAttrForm{
518
			{DW_AT_name, DW_FORM_string},
519
			{DW_AT_type, DW_FORM_ref_addr},
520
			{DW_AT_const_value, DW_FORM_sdata},
521
		},
522
	},
523

524
	/* AUTO */
525
	{
526
		DW_TAG_variable,
527
		DW_CHILDREN_no,
528
		[]dwAttrForm{
529
			{DW_AT_name, DW_FORM_string},
530
			{DW_AT_decl_line, DW_FORM_udata},
531
			{DW_AT_type, DW_FORM_ref_addr},
532
			{DW_AT_location, DW_FORM_block1},
533
		},
534
	},
535

536
	/* AUTO_LOCLIST */
537
	{
538
		DW_TAG_variable,
539
		DW_CHILDREN_no,
540
		[]dwAttrForm{
541
			{DW_AT_name, DW_FORM_string},
542
			{DW_AT_decl_line, DW_FORM_udata},
543
			{DW_AT_type, DW_FORM_ref_addr},
544
			{DW_AT_location, DW_FORM_sec_offset},
545
		},
546
	},
547

548
	/* AUTO_ABSTRACT */
549
	{
550
		DW_TAG_variable,
551
		DW_CHILDREN_no,
552
		[]dwAttrForm{
553
			{DW_AT_name, DW_FORM_string},
554
			{DW_AT_decl_line, DW_FORM_udata},
555
			{DW_AT_type, DW_FORM_ref_addr},
556
		},
557
	},
558

559
	/* AUTO_CONCRETE */
560
	{
561
		DW_TAG_variable,
562
		DW_CHILDREN_no,
563
		[]dwAttrForm{
564
			{DW_AT_abstract_origin, DW_FORM_ref_addr},
565
			{DW_AT_location, DW_FORM_block1},
566
		},
567
	},
568

569
	/* AUTO_CONCRETE_LOCLIST */
570
	{
571
		DW_TAG_variable,
572
		DW_CHILDREN_no,
573
		[]dwAttrForm{
574
			{DW_AT_abstract_origin, DW_FORM_ref_addr},
575
			{DW_AT_location, DW_FORM_sec_offset},
576
		},
577
	},
578

579
	/* PARAM */
580
	{
581
		DW_TAG_formal_parameter,
582
		DW_CHILDREN_no,
583
		[]dwAttrForm{
584
			{DW_AT_name, DW_FORM_string},
585
			{DW_AT_variable_parameter, DW_FORM_flag},
586
			{DW_AT_decl_line, DW_FORM_udata},
587
			{DW_AT_type, DW_FORM_ref_addr},
588
			{DW_AT_location, DW_FORM_block1},
589
		},
590
	},
591

592
	/* PARAM_LOCLIST */
593
	{
594
		DW_TAG_formal_parameter,
595
		DW_CHILDREN_no,
596
		[]dwAttrForm{
597
			{DW_AT_name, DW_FORM_string},
598
			{DW_AT_variable_parameter, DW_FORM_flag},
599
			{DW_AT_decl_line, DW_FORM_udata},
600
			{DW_AT_type, DW_FORM_ref_addr},
601
			{DW_AT_location, DW_FORM_sec_offset},
602
		},
603
	},
604

605
	/* PARAM_ABSTRACT */
606
	{
607
		DW_TAG_formal_parameter,
608
		DW_CHILDREN_no,
609
		[]dwAttrForm{
610
			{DW_AT_name, DW_FORM_string},
611
			{DW_AT_variable_parameter, DW_FORM_flag},
612
			{DW_AT_type, DW_FORM_ref_addr},
613
		},
614
	},
615

616
	/* PARAM_CONCRETE */
617
	{
618
		DW_TAG_formal_parameter,
619
		DW_CHILDREN_no,
620
		[]dwAttrForm{
621
			{DW_AT_abstract_origin, DW_FORM_ref_addr},
622
			{DW_AT_location, DW_FORM_block1},
623
		},
624
	},
625

626
	/* PARAM_CONCRETE_LOCLIST */
627
	{
628
		DW_TAG_formal_parameter,
629
		DW_CHILDREN_no,
630
		[]dwAttrForm{
631
			{DW_AT_abstract_origin, DW_FORM_ref_addr},
632
			{DW_AT_location, DW_FORM_sec_offset},
633
		},
634
	},
635

636
	/* LEXICAL_BLOCK_RANGES */
637
	{
638
		DW_TAG_lexical_block,
639
		DW_CHILDREN_yes,
640
		[]dwAttrForm{
641
			{DW_AT_ranges, DW_FORM_sec_offset},
642
		},
643
	},
644

645
	/* LEXICAL_BLOCK_SIMPLE */
646
	{
647
		DW_TAG_lexical_block,
648
		DW_CHILDREN_yes,
649
		[]dwAttrForm{
650
			{DW_AT_low_pc, DW_FORM_addr},
651
			{DW_AT_high_pc, DW_FORM_addr},
652
		},
653
	},
654

655
	/* STRUCTFIELD */
656
	{
657
		DW_TAG_member,
658
		DW_CHILDREN_no,
659
		[]dwAttrForm{
660
			{DW_AT_name, DW_FORM_string},
661
			{DW_AT_data_member_location, DW_FORM_udata},
662
			{DW_AT_type, DW_FORM_ref_addr},
663
			{DW_AT_go_embedded_field, DW_FORM_flag},
664
		},
665
	},
666

667
	/* FUNCTYPEPARAM */
668
	{
669
		DW_TAG_formal_parameter,
670
		DW_CHILDREN_no,
671

672
		// No name!
673
		[]dwAttrForm{
674
			{DW_AT_type, DW_FORM_ref_addr},
675
		},
676
	},
677

678
	/* DOTDOTDOT */
679
	{
680
		DW_TAG_unspecified_parameters,
681
		DW_CHILDREN_no,
682
		[]dwAttrForm{},
683
	},
684

685
	/* ARRAYRANGE */
686
	{
687
		DW_TAG_subrange_type,
688
		DW_CHILDREN_no,
689

690
		// No name!
691
		[]dwAttrForm{
692
			{DW_AT_type, DW_FORM_ref_addr},
693
			{DW_AT_count, DW_FORM_udata},
694
		},
695
	},
696

697
	// Below here are the types considered public by ispubtype
698
	/* NULLTYPE */
699
	{
700
		DW_TAG_unspecified_type,
701
		DW_CHILDREN_no,
702
		[]dwAttrForm{
703
			{DW_AT_name, DW_FORM_string},
704
		},
705
	},
706

707
	/* BASETYPE */
708
	{
709
		DW_TAG_base_type,
710
		DW_CHILDREN_no,
711
		[]dwAttrForm{
712
			{DW_AT_name, DW_FORM_string},
713
			{DW_AT_encoding, DW_FORM_data1},
714
			{DW_AT_byte_size, DW_FORM_data1},
715
			{DW_AT_go_kind, DW_FORM_data1},
716
			{DW_AT_go_runtime_type, DW_FORM_addr},
717
		},
718
	},
719

720
	/* ARRAYTYPE */
721
	// child is subrange with upper bound
722
	{
723
		DW_TAG_array_type,
724
		DW_CHILDREN_yes,
725
		[]dwAttrForm{
726
			{DW_AT_name, DW_FORM_string},
727
			{DW_AT_type, DW_FORM_ref_addr},
728
			{DW_AT_byte_size, DW_FORM_udata},
729
			{DW_AT_go_kind, DW_FORM_data1},
730
			{DW_AT_go_runtime_type, DW_FORM_addr},
731
		},
732
	},
733

734
	/* CHANTYPE */
735
	{
736
		DW_TAG_typedef,
737
		DW_CHILDREN_no,
738
		[]dwAttrForm{
739
			{DW_AT_name, DW_FORM_string},
740
			{DW_AT_type, DW_FORM_ref_addr},
741
			{DW_AT_go_kind, DW_FORM_data1},
742
			{DW_AT_go_runtime_type, DW_FORM_addr},
743
			{DW_AT_go_elem, DW_FORM_ref_addr},
744
		},
745
	},
746

747
	/* FUNCTYPE */
748
	{
749
		DW_TAG_subroutine_type,
750
		DW_CHILDREN_yes,
751
		[]dwAttrForm{
752
			{DW_AT_name, DW_FORM_string},
753
			{DW_AT_byte_size, DW_FORM_udata},
754
			{DW_AT_go_kind, DW_FORM_data1},
755
			{DW_AT_go_runtime_type, DW_FORM_addr},
756
		},
757
	},
758

759
	/* IFACETYPE */
760
	{
761
		DW_TAG_typedef,
762
		DW_CHILDREN_yes,
763
		[]dwAttrForm{
764
			{DW_AT_name, DW_FORM_string},
765
			{DW_AT_type, DW_FORM_ref_addr},
766
			{DW_AT_go_kind, DW_FORM_data1},
767
			{DW_AT_go_runtime_type, DW_FORM_addr},
768
		},
769
	},
770

771
	/* MAPTYPE */
772
	{
773
		DW_TAG_typedef,
774
		DW_CHILDREN_no,
775
		[]dwAttrForm{
776
			{DW_AT_name, DW_FORM_string},
777
			{DW_AT_type, DW_FORM_ref_addr},
778
			{DW_AT_go_kind, DW_FORM_data1},
779
			{DW_AT_go_runtime_type, DW_FORM_addr},
780
			{DW_AT_go_key, DW_FORM_ref_addr},
781
			{DW_AT_go_elem, DW_FORM_ref_addr},
782
		},
783
	},
784

785
	/* PTRTYPE */
786
	{
787
		DW_TAG_pointer_type,
788
		DW_CHILDREN_no,
789
		[]dwAttrForm{
790
			{DW_AT_name, DW_FORM_string},
791
			{DW_AT_type, DW_FORM_ref_addr},
792
			{DW_AT_go_kind, DW_FORM_data1},
793
			{DW_AT_go_runtime_type, DW_FORM_addr},
794
		},
795
	},
796

797
	/* BARE_PTRTYPE */
798
	{
799
		DW_TAG_pointer_type,
800
		DW_CHILDREN_no,
801
		[]dwAttrForm{
802
			{DW_AT_name, DW_FORM_string},
803
		},
804
	},
805

806
	/* SLICETYPE */
807
	{
808
		DW_TAG_structure_type,
809
		DW_CHILDREN_yes,
810
		[]dwAttrForm{
811
			{DW_AT_name, DW_FORM_string},
812
			{DW_AT_byte_size, DW_FORM_udata},
813
			{DW_AT_go_kind, DW_FORM_data1},
814
			{DW_AT_go_runtime_type, DW_FORM_addr},
815
			{DW_AT_go_elem, DW_FORM_ref_addr},
816
		},
817
	},
818

819
	/* STRINGTYPE */
820
	{
821
		DW_TAG_structure_type,
822
		DW_CHILDREN_yes,
823
		[]dwAttrForm{
824
			{DW_AT_name, DW_FORM_string},
825
			{DW_AT_byte_size, DW_FORM_udata},
826
			{DW_AT_go_kind, DW_FORM_data1},
827
			{DW_AT_go_runtime_type, DW_FORM_addr},
828
		},
829
	},
830

831
	/* STRUCTTYPE */
832
	{
833
		DW_TAG_structure_type,
834
		DW_CHILDREN_yes,
835
		[]dwAttrForm{
836
			{DW_AT_name, DW_FORM_string},
837
			{DW_AT_byte_size, DW_FORM_udata},
838
			{DW_AT_go_kind, DW_FORM_data1},
839
			{DW_AT_go_runtime_type, DW_FORM_addr},
840
		},
841
	},
842

843
	/* TYPEDECL */
844
	{
845
		DW_TAG_typedef,
846
		DW_CHILDREN_no,
847
		[]dwAttrForm{
848
			{DW_AT_name, DW_FORM_string},
849
			{DW_AT_type, DW_FORM_ref_addr},
850
		},
851
	},
852
}
853

854
// GetAbbrev returns the contents of the .debug_abbrev section.
855
func GetAbbrev() []byte {
856
	abbrevs := Abbrevs()
857
	var buf []byte
858
	for i := 1; i < DW_NABRV; i++ {
859
		// See section 7.5.3
860
		buf = AppendUleb128(buf, uint64(i))
861
		buf = AppendUleb128(buf, uint64(abbrevs[i].tag))
862
		buf = append(buf, abbrevs[i].children)
863
		for _, f := range abbrevs[i].attr {
864
			buf = AppendUleb128(buf, uint64(f.attr))
865
			buf = AppendUleb128(buf, uint64(f.form))
866
		}
867
		buf = append(buf, 0, 0)
868
	}
869
	return append(buf, 0)
870
}
871

872
/*
873
 * Debugging Information Entries and their attributes.
874
 */
875

876
// DWAttr represents an attribute of a DWDie.
877
//
878
// For DW_CLS_string and _block, value should contain the length, and
879
// data the data, for _reference, value is 0 and data is a DWDie* to
880
// the referenced instance, for all others, value is the whole thing
881
// and data is null.
882
type DWAttr struct {
883
	Link  *DWAttr
884
	Atr   uint16 // DW_AT_
885
	Cls   uint8  // DW_CLS_
886
	Value int64
887
	Data  interface{}
888
}
889

890
// DWDie represents a DWARF debug info entry.
891
type DWDie struct {
892
	Abbrev int
893
	Link   *DWDie
894
	Child  *DWDie
895
	Attr   *DWAttr
896
	Sym    Sym
897
}
898

899
func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, data interface{}) error {
900
	switch form {
901
	case DW_FORM_addr: // address
902
		// Allow nil addresses for DW_AT_go_runtime_type.
903
		if data == nil && value == 0 {
904
			ctxt.AddInt(s, ctxt.PtrSize(), 0)
905
			break
906
		}
907
		if cls == DW_CLS_GO_TYPEREF {
908
			ctxt.AddSectionOffset(s, ctxt.PtrSize(), data, value)
909
			break
910
		}
911
		ctxt.AddAddress(s, data, value)
912

913
	case DW_FORM_block1: // block
914
		if cls == DW_CLS_ADDRESS {
915
			ctxt.AddInt(s, 1, int64(1+ctxt.PtrSize()))
916
			ctxt.AddInt(s, 1, DW_OP_addr)
917
			ctxt.AddAddress(s, data, 0)
918
			break
919
		}
920

921
		value &= 0xff
922
		ctxt.AddInt(s, 1, value)
923
		p := data.([]byte)[:value]
924
		ctxt.AddBytes(s, p)
925

926
	case DW_FORM_block2: // block
927
		value &= 0xffff
928

929
		ctxt.AddInt(s, 2, value)
930
		p := data.([]byte)[:value]
931
		ctxt.AddBytes(s, p)
932

933
	case DW_FORM_block4: // block
934
		value &= 0xffffffff
935

936
		ctxt.AddInt(s, 4, value)
937
		p := data.([]byte)[:value]
938
		ctxt.AddBytes(s, p)
939

940
	case DW_FORM_block: // block
941
		Uleb128put(ctxt, s, value)
942

943
		p := data.([]byte)[:value]
944
		ctxt.AddBytes(s, p)
945

946
	case DW_FORM_data1: // constant
947
		ctxt.AddInt(s, 1, value)
948

949
	case DW_FORM_data2: // constant
950
		ctxt.AddInt(s, 2, value)
951

952
	case DW_FORM_data4: // constant, {line,loclist,mac,rangelist}ptr
953
		if cls == DW_CLS_PTR { // DW_AT_stmt_list and DW_AT_ranges
954
			ctxt.AddDWARFAddrSectionOffset(s, data, value)
955
			break
956
		}
957
		ctxt.AddInt(s, 4, value)
958

959
	case DW_FORM_data8: // constant, {line,loclist,mac,rangelist}ptr
960
		ctxt.AddInt(s, 8, value)
961

962
	case DW_FORM_sdata: // constant
963
		Sleb128put(ctxt, s, value)
964

965
	case DW_FORM_udata: // constant
966
		Uleb128put(ctxt, s, value)
967

968
	case DW_FORM_string: // string
969
		str := data.(string)
970
		ctxt.AddString(s, str)
971
		// TODO(ribrdb): verify padded strings are never used and remove this
972
		for i := int64(len(str)); i < value; i++ {
973
			ctxt.AddInt(s, 1, 0)
974
		}
975

976
	case DW_FORM_flag: // flag
977
		if value != 0 {
978
			ctxt.AddInt(s, 1, 1)
979
		} else {
980
			ctxt.AddInt(s, 1, 0)
981
		}
982

983
	// As of DWARF 3 the ref_addr is always 32 bits, unless emitting a large
984
	// (> 4 GB of debug info aka "64-bit") unit, which we don't implement.
985
	case DW_FORM_ref_addr: // reference to a DIE in the .info section
986
		fallthrough
987
	case DW_FORM_sec_offset: // offset into a DWARF section other than .info
988
		if data == nil {
989
			return fmt.Errorf("dwarf: null reference in %d", abbrev)
990
		}
991
		ctxt.AddDWARFAddrSectionOffset(s, data, value)
992

993
	case DW_FORM_ref1, // reference within the compilation unit
994
		DW_FORM_ref2,      // reference
995
		DW_FORM_ref4,      // reference
996
		DW_FORM_ref8,      // reference
997
		DW_FORM_ref_udata, // reference
998

999
		DW_FORM_strp,     // string
1000
		DW_FORM_indirect: // (see Section 7.5.3)
1001
		fallthrough
1002
	default:
1003
		return fmt.Errorf("dwarf: unsupported attribute form %d / class %d", form, cls)
1004
	}
1005
	return nil
1006
}
1007

1008
// PutAttrs writes the attributes for a DIE to symbol 's'.
1009
//
1010
// Note that we can (and do) add arbitrary attributes to a DIE, but
1011
// only the ones actually listed in the Abbrev will be written out.
1012
func PutAttrs(ctxt Context, s Sym, abbrev int, attr *DWAttr) {
1013
	abbrevs := Abbrevs()
1014
Outer:
1015
	for _, f := range abbrevs[abbrev].attr {
1016
		for ap := attr; ap != nil; ap = ap.Link {
1017
			if ap.Atr == f.attr {
1018
				putattr(ctxt, s, abbrev, int(f.form), int(ap.Cls), ap.Value, ap.Data)
1019
				continue Outer
1020
			}
1021
		}
1022

1023
		putattr(ctxt, s, abbrev, int(f.form), 0, 0, nil)
1024
	}
1025
}
1026

1027
// HasChildren reports whether 'die' uses an abbrev that supports children.
1028
func HasChildren(die *DWDie) bool {
1029
	abbrevs := Abbrevs()
1030
	return abbrevs[die.Abbrev].children != 0
1031
}
1032

1033
// PutIntConst writes a DIE for an integer constant
1034
func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) {
1035
	Uleb128put(ctxt, info, DW_ABRV_INT_CONSTANT)
1036
	putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
1037
	putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ)
1038
	putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_sdata, DW_CLS_CONSTANT, val, nil)
1039
}
1040

1041
// PutBasedRanges writes a range table to sym. All addresses in ranges are
1042
// relative to some base address, which must be arranged by the caller
1043
// (e.g., with a DW_AT_low_pc attribute, or in a BASE-prefixed range).
1044
func PutBasedRanges(ctxt Context, sym Sym, ranges []Range) {
1045
	ps := ctxt.PtrSize()
1046
	// Write ranges.
1047
	for _, r := range ranges {
1048
		ctxt.AddInt(sym, ps, r.Start)
1049
		ctxt.AddInt(sym, ps, r.End)
1050
	}
1051
	// Write trailer.
1052
	ctxt.AddInt(sym, ps, 0)
1053
	ctxt.AddInt(sym, ps, 0)
1054
}
1055

1056
// PutRanges writes a range table to s.Ranges.
1057
// All addresses in ranges are relative to s.base.
1058
func (s *FnState) PutRanges(ctxt Context, ranges []Range) {
1059
	ps := ctxt.PtrSize()
1060
	sym, base := s.Ranges, s.StartPC
1061

1062
	if s.UseBASEntries {
1063
		// Using a Base Address Selection Entry reduces the number of relocations, but
1064
		// this is not done on macOS because it is not supported by dsymutil/dwarfdump/lldb
1065
		ctxt.AddInt(sym, ps, -1)
1066
		ctxt.AddAddress(sym, base, 0)
1067
		PutBasedRanges(ctxt, sym, ranges)
1068
		return
1069
	}
1070

1071
	// Write ranges full of relocations
1072
	for _, r := range ranges {
1073
		ctxt.AddCURelativeAddress(sym, base, r.Start)
1074
		ctxt.AddCURelativeAddress(sym, base, r.End)
1075
	}
1076
	// Write trailer.
1077
	ctxt.AddInt(sym, ps, 0)
1078
	ctxt.AddInt(sym, ps, 0)
1079
}
1080

1081
// Return TRUE if the inlined call in the specified slot is empty,
1082
// meaning it has a zero-length range (no instructions), and all
1083
// of its children are empty.
1084
func isEmptyInlinedCall(slot int, calls *InlCalls) bool {
1085
	ic := &calls.Calls[slot]
1086
	if ic.InlIndex == -2 {
1087
		return true
1088
	}
1089
	live := false
1090
	for _, k := range ic.Children {
1091
		if !isEmptyInlinedCall(k, calls) {
1092
			live = true
1093
		}
1094
	}
1095
	if len(ic.Ranges) > 0 {
1096
		live = true
1097
	}
1098
	if !live {
1099
		ic.InlIndex = -2
1100
	}
1101
	return !live
1102
}
1103

1104
// Slot -1:    return top-level inlines
1105
// Slot >= 0:  return children of that slot
1106
func inlChildren(slot int, calls *InlCalls) []int {
1107
	var kids []int
1108
	if slot != -1 {
1109
		for _, k := range calls.Calls[slot].Children {
1110
			if !isEmptyInlinedCall(k, calls) {
1111
				kids = append(kids, k)
1112
			}
1113
		}
1114
	} else {
1115
		for k := 0; k < len(calls.Calls); k += 1 {
1116
			if calls.Calls[k].Root && !isEmptyInlinedCall(k, calls) {
1117
				kids = append(kids, k)
1118
			}
1119
		}
1120
	}
1121
	return kids
1122
}
1123

1124
func inlinedVarTable(inlcalls *InlCalls) map[*Var]bool {
1125
	vars := make(map[*Var]bool)
1126
	for _, ic := range inlcalls.Calls {
1127
		for _, v := range ic.InlVars {
1128
			vars[v] = true
1129
		}
1130
	}
1131
	return vars
1132
}
1133

1134
// The s.Scopes slice contains variables were originally part of the
1135
// function being emitted, as well as variables that were imported
1136
// from various callee functions during the inlining process. This
1137
// function prunes out any variables from the latter category (since
1138
// they will be emitted as part of DWARF inlined_subroutine DIEs) and
1139
// then generates scopes for vars in the former category.
1140
func putPrunedScopes(ctxt Context, s *FnState, fnabbrev int) error {
1141
	if len(s.Scopes) == 0 {
1142
		return nil
1143
	}
1144
	scopes := make([]Scope, len(s.Scopes), len(s.Scopes))
1145
	pvars := inlinedVarTable(&s.InlCalls)
1146
	for k, s := range s.Scopes {
1147
		var pruned Scope = Scope{Parent: s.Parent, Ranges: s.Ranges}
1148
		for i := 0; i < len(s.Vars); i++ {
1149
			_, found := pvars[s.Vars[i]]
1150
			if !found {
1151
				pruned.Vars = append(pruned.Vars, s.Vars[i])
1152
			}
1153
		}
1154
		sort.Sort(byChildIndex(pruned.Vars))
1155
		scopes[k] = pruned
1156
	}
1157
	var encbuf [20]byte
1158
	if putscope(ctxt, s, scopes, 0, fnabbrev, encbuf[:0]) < int32(len(scopes)) {
1159
		return errors.New("multiple toplevel scopes")
1160
	}
1161
	return nil
1162
}
1163

1164
// Emit DWARF attributes and child DIEs for an 'abstract' subprogram.
1165
// The abstract subprogram DIE for a function contains its
1166
// location-independent attributes (name, type, etc). Other instances
1167
// of the function (any inlined copy of it, or the single out-of-line
1168
// 'concrete' instance) will contain a pointer back to this abstract
1169
// DIE (as a space-saving measure, so that name/type etc doesn't have
1170
// to be repeated for each inlined copy).
1171
func PutAbstractFunc(ctxt Context, s *FnState) error {
1172

1173
	if logDwarf {
1174
		ctxt.Logf("PutAbstractFunc(%v)\n", s.Absfn)
1175
	}
1176

1177
	abbrev := DW_ABRV_FUNCTION_ABSTRACT
1178
	Uleb128put(ctxt, s.Absfn, int64(abbrev))
1179

1180
	fullname := s.Name
1181
	if strings.HasPrefix(s.Name, "\"\".") {
1182
		// Generate a fully qualified name for the function in the
1183
		// abstract case. This is so as to avoid the need for the
1184
		// linker to process the DIE with patchDWARFName(); we can't
1185
		// allow the name attribute of an abstract subprogram DIE to
1186
		// be rewritten, since it would change the offsets of the
1187
		// child DIEs (which we're relying on in order for abstract
1188
		// origin references to work).
1189
		fullname = objabi.PathToPrefix(s.Importpath) + "." + s.Name[3:]
1190
	}
1191
	putattr(ctxt, s.Absfn, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(fullname)), fullname)
1192

1193
	// DW_AT_inlined value
1194
	putattr(ctxt, s.Absfn, abbrev, DW_FORM_data1, DW_CLS_CONSTANT, int64(DW_INL_inlined), nil)
1195

1196
	var ev int64
1197
	if s.External {
1198
		ev = 1
1199
	}
1200
	putattr(ctxt, s.Absfn, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
1201

1202
	// Child variables (may be empty)
1203
	var flattened []*Var
1204

1205
	// This slice will hold the offset in bytes for each child var DIE
1206
	// with respect to the start of the parent subprogram DIE.
1207
	var offsets []int32
1208

1209
	// Scopes/vars
1210
	if len(s.Scopes) > 0 {
1211
		// For abstract subprogram DIEs we want to flatten out scope info:
1212
		// lexical scope DIEs contain range and/or hi/lo PC attributes,
1213
		// which we explicitly don't want for the abstract subprogram DIE.
1214
		pvars := inlinedVarTable(&s.InlCalls)
1215
		for _, scope := range s.Scopes {
1216
			for i := 0; i < len(scope.Vars); i++ {
1217
				_, found := pvars[scope.Vars[i]]
1218
				if found || !scope.Vars[i].IsInAbstract {
1219
					continue
1220
				}
1221
				flattened = append(flattened, scope.Vars[i])
1222
			}
1223
		}
1224
		if len(flattened) > 0 {
1225
			sort.Sort(byChildIndex(flattened))
1226

1227
			if logDwarf {
1228
				ctxt.Logf("putAbstractScope(%v): vars:", s.Info)
1229
				for i, v := range flattened {
1230
					ctxt.Logf(" %d:%s", i, v.Name)
1231
				}
1232
				ctxt.Logf("\n")
1233
			}
1234

1235
			// This slice will hold the offset in bytes for each child
1236
			// variable DIE with respect to the start of the parent
1237
			// subprogram DIE.
1238
			for _, v := range flattened {
1239
				offsets = append(offsets, int32(ctxt.CurrentOffset(s.Absfn)))
1240
				putAbstractVar(ctxt, s.Absfn, v)
1241
			}
1242
		}
1243
	}
1244
	ctxt.RecordChildDieOffsets(s.Absfn, flattened, offsets)
1245

1246
	Uleb128put(ctxt, s.Absfn, 0)
1247
	return nil
1248
}
1249

1250
// Emit DWARF attributes and child DIEs for an inlined subroutine. The
1251
// first attribute of an inlined subroutine DIE is a reference back to
1252
// its corresponding 'abstract' DIE (containing location-independent
1253
// attributes such as name, type, etc). Inlined subroutine DIEs can
1254
// have other inlined subroutine DIEs as children.
1255
func PutInlinedFunc(ctxt Context, s *FnState, callersym Sym, callIdx int) error {
1256
	ic := s.InlCalls.Calls[callIdx]
1257
	callee := ic.AbsFunSym
1258

1259
	abbrev := DW_ABRV_INLINED_SUBROUTINE_RANGES
1260
	if len(ic.Ranges) == 1 {
1261
		abbrev = DW_ABRV_INLINED_SUBROUTINE
1262
	}
1263
	Uleb128put(ctxt, s.Info, int64(abbrev))
1264

1265
	if logDwarf {
1266
		ctxt.Logf("PutInlinedFunc(caller=%v,callee=%v,abbrev=%d)\n", callersym, callee, abbrev)
1267
	}
1268

1269
	// Abstract origin.
1270
	putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, callee)
1271

1272
	if abbrev == DW_ABRV_INLINED_SUBROUTINE_RANGES {
1273
		putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, s.Ranges.Length(ctxt), s.Ranges)
1274
		s.PutRanges(ctxt, ic.Ranges)
1275
	} else {
1276
		st := ic.Ranges[0].Start
1277
		en := ic.Ranges[0].End
1278
		putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, st, s.StartPC)
1279
		putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, en, s.StartPC)
1280
	}
1281

1282
	// Emit call file, line attrs.
1283
	ctxt.AddFileRef(s.Info, ic.CallFile)
1284
	form := int(expandPseudoForm(DW_FORM_udata_pseudo))
1285
	putattr(ctxt, s.Info, abbrev, form, DW_CLS_CONSTANT, int64(ic.CallLine), nil)
1286

1287
	// Variables associated with this inlined routine instance.
1288
	vars := ic.InlVars
1289
	sort.Sort(byChildIndex(vars))
1290
	inlIndex := ic.InlIndex
1291
	var encbuf [20]byte
1292
	for _, v := range vars {
1293
		if !v.IsInAbstract {
1294
			continue
1295
		}
1296
		putvar(ctxt, s, v, callee, abbrev, inlIndex, encbuf[:0])
1297
	}
1298

1299
	// Children of this inline.
1300
	for _, sib := range inlChildren(callIdx, &s.InlCalls) {
1301
		absfn := s.InlCalls.Calls[sib].AbsFunSym
1302
		err := PutInlinedFunc(ctxt, s, absfn, sib)
1303
		if err != nil {
1304
			return err
1305
		}
1306
	}
1307

1308
	Uleb128put(ctxt, s.Info, 0)
1309
	return nil
1310
}
1311

1312
// Emit DWARF attributes and child DIEs for a 'concrete' subprogram,
1313
// meaning the out-of-line copy of a function that was inlined at some
1314
// point during the compilation of its containing package. The first
1315
// attribute for a concrete DIE is a reference to the 'abstract' DIE
1316
// for the function (which holds location-independent attributes such
1317
// as name, type), then the remainder of the attributes are specific
1318
// to this instance (location, frame base, etc).
1319
func PutConcreteFunc(ctxt Context, s *FnState) error {
1320
	if logDwarf {
1321
		ctxt.Logf("PutConcreteFunc(%v)\n", s.Info)
1322
	}
1323
	abbrev := DW_ABRV_FUNCTION_CONCRETE
1324
	Uleb128put(ctxt, s.Info, int64(abbrev))
1325

1326
	// Abstract origin.
1327
	putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, s.Absfn)
1328

1329
	// Start/end PC.
1330
	putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, 0, s.StartPC)
1331
	putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, s.Size, s.StartPC)
1332

1333
	// cfa / frame base
1334
	putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
1335

1336
	// Scopes
1337
	if err := putPrunedScopes(ctxt, s, abbrev); err != nil {
1338
		return err
1339
	}
1340

1341
	// Inlined subroutines.
1342
	for _, sib := range inlChildren(-1, &s.InlCalls) {
1343
		absfn := s.InlCalls.Calls[sib].AbsFunSym
1344
		err := PutInlinedFunc(ctxt, s, absfn, sib)
1345
		if err != nil {
1346
			return err
1347
		}
1348
	}
1349

1350
	Uleb128put(ctxt, s.Info, 0)
1351
	return nil
1352
}
1353

1354
// Emit DWARF attributes and child DIEs for a subprogram. Here
1355
// 'default' implies that the function in question was not inlined
1356
// when its containing package was compiled (hence there is no need to
1357
// emit an abstract version for it to use as a base for inlined
1358
// routine records).
1359
func PutDefaultFunc(ctxt Context, s *FnState) error {
1360
	if logDwarf {
1361
		ctxt.Logf("PutDefaultFunc(%v)\n", s.Info)
1362
	}
1363
	abbrev := DW_ABRV_FUNCTION
1364
	Uleb128put(ctxt, s.Info, int64(abbrev))
1365

1366
	// Expand '"".' to import path.
1367
	name := s.Name
1368
	if s.Importpath != "" {
1369
		name = strings.Replace(name, "\"\".", objabi.PathToPrefix(s.Importpath)+".", -1)
1370
	}
1371

1372
	putattr(ctxt, s.Info, DW_ABRV_FUNCTION, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
1373
	putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, 0, s.StartPC)
1374
	putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, s.Size, s.StartPC)
1375
	putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
1376
	ctxt.AddFileRef(s.Info, s.Filesym)
1377

1378
	var ev int64
1379
	if s.External {
1380
		ev = 1
1381
	}
1382
	putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
1383

1384
	// Scopes
1385
	if err := putPrunedScopes(ctxt, s, abbrev); err != nil {
1386
		return err
1387
	}
1388

1389
	// Inlined subroutines.
1390
	for _, sib := range inlChildren(-1, &s.InlCalls) {
1391
		absfn := s.InlCalls.Calls[sib].AbsFunSym
1392
		err := PutInlinedFunc(ctxt, s, absfn, sib)
1393
		if err != nil {
1394
			return err
1395
		}
1396
	}
1397

1398
	Uleb128put(ctxt, s.Info, 0)
1399
	return nil
1400
}
1401

1402
func putscope(ctxt Context, s *FnState, scopes []Scope, curscope int32, fnabbrev int, encbuf []byte) int32 {
1403

1404
	if logDwarf {
1405
		ctxt.Logf("putscope(%v,%d): vars:", s.Info, curscope)
1406
		for i, v := range scopes[curscope].Vars {
1407
			ctxt.Logf(" %d:%d:%s", i, v.ChildIndex, v.Name)
1408
		}
1409
		ctxt.Logf("\n")
1410
	}
1411

1412
	for _, v := range scopes[curscope].Vars {
1413
		putvar(ctxt, s, v, s.Absfn, fnabbrev, -1, encbuf)
1414
	}
1415
	this := curscope
1416
	curscope++
1417
	for curscope < int32(len(scopes)) {
1418
		scope := scopes[curscope]
1419
		if scope.Parent != this {
1420
			return curscope
1421
		}
1422

1423
		if len(scopes[curscope].Vars) == 0 {
1424
			curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf)
1425
			continue
1426
		}
1427

1428
		if len(scope.Ranges) == 1 {
1429
			Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE)
1430
			putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].Start, s.StartPC)
1431
			putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].End, s.StartPC)
1432
		} else {
1433
			Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES)
1434
			putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES, DW_FORM_sec_offset, DW_CLS_PTR, s.Ranges.Length(ctxt), s.Ranges)
1435

1436
			s.PutRanges(ctxt, scope.Ranges)
1437
		}
1438

1439
		curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf)
1440

1441
		Uleb128put(ctxt, s.Info, 0)
1442
	}
1443
	return curscope
1444
}
1445

1446
// Given a default var abbrev code, select corresponding concrete code.
1447
func concreteVarAbbrev(varAbbrev int) int {
1448
	switch varAbbrev {
1449
	case DW_ABRV_AUTO:
1450
		return DW_ABRV_AUTO_CONCRETE
1451
	case DW_ABRV_PARAM:
1452
		return DW_ABRV_PARAM_CONCRETE
1453
	case DW_ABRV_AUTO_LOCLIST:
1454
		return DW_ABRV_AUTO_CONCRETE_LOCLIST
1455
	case DW_ABRV_PARAM_LOCLIST:
1456
		return DW_ABRV_PARAM_CONCRETE_LOCLIST
1457
	default:
1458
		panic("should never happen")
1459
	}
1460
}
1461

1462
// Pick the correct abbrev code for variable or parameter DIE.
1463
func determineVarAbbrev(v *Var, fnabbrev int) (int, bool, bool) {
1464
	abbrev := v.Abbrev
1465

1466
	// If the variable was entirely optimized out, don't emit a location list;
1467
	// convert to an inline abbreviation and emit an empty location.
1468
	missing := false
1469
	switch {
1470
	case abbrev == DW_ABRV_AUTO_LOCLIST && v.PutLocationList == nil:
1471
		missing = true
1472
		abbrev = DW_ABRV_AUTO
1473
	case abbrev == DW_ABRV_PARAM_LOCLIST && v.PutLocationList == nil:
1474
		missing = true
1475
		abbrev = DW_ABRV_PARAM
1476
	}
1477

1478
	// Determine whether to use a concrete variable or regular variable DIE.
1479
	concrete := true
1480
	switch fnabbrev {
1481
	case DW_ABRV_FUNCTION:
1482
		concrete = false
1483
		break
1484
	case DW_ABRV_FUNCTION_CONCRETE:
1485
		// If we're emitting a concrete subprogram DIE and the variable
1486
		// in question is not part of the corresponding abstract function DIE,
1487
		// then use the default (non-concrete) abbrev for this param.
1488
		if !v.IsInAbstract {
1489
			concrete = false
1490
		}
1491
	case DW_ABRV_INLINED_SUBROUTINE, DW_ABRV_INLINED_SUBROUTINE_RANGES:
1492
	default:
1493
		panic("should never happen")
1494
	}
1495

1496
	// Select proper abbrev based on concrete/non-concrete
1497
	if concrete {
1498
		abbrev = concreteVarAbbrev(abbrev)
1499
	}
1500

1501
	return abbrev, missing, concrete
1502
}
1503

1504
func abbrevUsesLoclist(abbrev int) bool {
1505
	switch abbrev {
1506
	case DW_ABRV_AUTO_LOCLIST, DW_ABRV_AUTO_CONCRETE_LOCLIST,
1507
		DW_ABRV_PARAM_LOCLIST, DW_ABRV_PARAM_CONCRETE_LOCLIST:
1508
		return true
1509
	default:
1510
		return false
1511
	}
1512
}
1513

1514
// Emit DWARF attributes for a variable belonging to an 'abstract' subprogram.
1515
func putAbstractVar(ctxt Context, info Sym, v *Var) {
1516
	// Remap abbrev
1517
	abbrev := v.Abbrev
1518
	switch abbrev {
1519
	case DW_ABRV_AUTO, DW_ABRV_AUTO_LOCLIST:
1520
		abbrev = DW_ABRV_AUTO_ABSTRACT
1521
	case DW_ABRV_PARAM, DW_ABRV_PARAM_LOCLIST:
1522
		abbrev = DW_ABRV_PARAM_ABSTRACT
1523
	}
1524

1525
	Uleb128put(ctxt, info, int64(abbrev))
1526
	putattr(ctxt, info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(v.Name)), v.Name)
1527

1528
	// Isreturn attribute if this is a param
1529
	if abbrev == DW_ABRV_PARAM_ABSTRACT {
1530
		var isReturn int64
1531
		if v.IsReturnValue {
1532
			isReturn = 1
1533
		}
1534
		putattr(ctxt, info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil)
1535
	}
1536

1537
	// Line
1538
	if abbrev != DW_ABRV_PARAM_ABSTRACT {
1539
		// See issue 23374 for more on why decl line is skipped for abs params.
1540
		putattr(ctxt, info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil)
1541
	}
1542

1543
	// Type
1544
	putattr(ctxt, info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
1545

1546
	// Var has no children => no terminator
1547
}
1548

1549
func putvar(ctxt Context, s *FnState, v *Var, absfn Sym, fnabbrev, inlIndex int, encbuf []byte) {
1550
	// Remap abbrev according to parent DIE abbrev
1551
	abbrev, missing, concrete := determineVarAbbrev(v, fnabbrev)
1552

1553
	Uleb128put(ctxt, s.Info, int64(abbrev))
1554

1555
	// Abstract origin for concrete / inlined case
1556
	if concrete {
1557
		// Here we are making a reference to a child DIE of an abstract
1558
		// function subprogram DIE. The child DIE has no LSym, so instead
1559
		// after the call to 'putattr' below we make a call to register
1560
		// the child DIE reference.
1561
		putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, absfn)
1562
		ctxt.RecordDclReference(s.Info, absfn, int(v.ChildIndex), inlIndex)
1563
	} else {
1564
		// Var name, line for abstract and default cases
1565
		n := v.Name
1566
		putattr(ctxt, s.Info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n)
1567
		if abbrev == DW_ABRV_PARAM || abbrev == DW_ABRV_PARAM_LOCLIST || abbrev == DW_ABRV_PARAM_ABSTRACT {
1568
			var isReturn int64
1569
			if v.IsReturnValue {
1570
				isReturn = 1
1571
			}
1572
			putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil)
1573
		}
1574
		putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil)
1575
		putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
1576
	}
1577

1578
	if abbrevUsesLoclist(abbrev) {
1579
		putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, s.Loc.Length(ctxt), s.Loc)
1580
		v.PutLocationList(s.Loc, s.StartPC)
1581
	} else {
1582
		loc := encbuf[:0]
1583
		switch {
1584
		case missing:
1585
			break // no location
1586
		case v.StackOffset == 0:
1587
			loc = append(loc, DW_OP_call_frame_cfa)
1588
		default:
1589
			loc = append(loc, DW_OP_fbreg)
1590
			loc = AppendSleb128(loc, int64(v.StackOffset))
1591
		}
1592
		putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, int64(len(loc)), loc)
1593
	}
1594

1595
	// Var has no children => no terminator
1596
}
1597

1598
// VarsByOffset attaches the methods of sort.Interface to []*Var,
1599
// sorting in increasing StackOffset.
1600
type VarsByOffset []*Var
1601

1602
func (s VarsByOffset) Len() int           { return len(s) }
1603
func (s VarsByOffset) Less(i, j int) bool { return s[i].StackOffset < s[j].StackOffset }
1604
func (s VarsByOffset) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
1605

1606
// byChildIndex implements sort.Interface for []*dwarf.Var by child index.
1607
type byChildIndex []*Var
1608

1609
func (s byChildIndex) Len() int           { return len(s) }
1610
func (s byChildIndex) Less(i, j int) bool { return s[i].ChildIndex < s[j].ChildIndex }
1611
func (s byChildIndex) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
1612

1613
// IsDWARFEnabledOnAIX returns true if DWARF is possible on the
1614
// current extld.
1615
// AIX ld doesn't support DWARF with -bnoobjreorder with version
1616
// prior to 7.2.2.
1617
func IsDWARFEnabledOnAIXLd(extld string) (bool, error) {
1618
	out, err := exec.Command(extld, "-Wl,-V").CombinedOutput()
1619
	if err != nil {
1620
		// The normal output should display ld version and
1621
		// then fails because ".main" is not defined:
1622
		// ld: 0711-317 ERROR: Undefined symbol: .main
1623
		if !bytes.Contains(out, []byte("0711-317")) {
1624
			return false, fmt.Errorf("%s -Wl,-V failed: %v\n%s", extld, err, out)
1625
		}
1626
	}
1627
	// gcc -Wl,-V output should be:
1628
	//   /usr/bin/ld: LD X.X.X(date)
1629
	//   ...
1630
	out = bytes.TrimPrefix(out, []byte("/usr/bin/ld: LD "))
1631
	vers := string(bytes.Split(out, []byte("("))[0])
1632
	subvers := strings.Split(vers, ".")
1633
	if len(subvers) != 3 {
1634
		return false, fmt.Errorf("cannot parse %s -Wl,-V (%s): %v\n", extld, out, err)
1635
	}
1636
	if v, err := strconv.Atoi(subvers[0]); err != nil || v < 7 {
1637
		return false, nil
1638
	} else if v > 7 {
1639
		return true, nil
1640
	}
1641
	if v, err := strconv.Atoi(subvers[1]); err != nil || v < 2 {
1642
		return false, nil
1643
	} else if v > 2 {
1644
		return true, nil
1645
	}
1646
	if v, err := strconv.Atoi(subvers[2]); err != nil || v < 2 {
1647
		return false, nil
1648
	}
1649
	return true, nil
1650
}
1651

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.