podman
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.
8package dwarf
9
10import (
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.
22const InfoPrefix = "go.info."
23
24// ConstInfoPrefix is the prefix for all symbols containing DWARF info
25// entries that contain constants.
26const ConstInfoPrefix = "go.constinfo."
27
28// CUInfoPrefix is the prefix for symbols containing information to
29// populate the DWARF compilation unit info entries.
30const CUInfoPrefix = "go.cuinfo."
31
32// Used to form the symbol name assigned to the DWARF 'abstract subprogram"
33// info entry for a function
34const AbstractFuncSuffix = "$abstract"
35
36// Controls logging/debugging for selected aspects of DWARF subprogram
37// generation (functions, scopes).
38var logDwarf bool
39
40// Sym represents a symbol.
41type Sym interface {
42Length(dwarfContext interface{}) int64
43}
44
45// A Var represents a local variable or a function parameter.
46type Var struct {
47Name string
48Abbrev int // Either DW_ABRV_AUTO[_LOCLIST] or DW_ABRV_PARAM[_LOCLIST]
49IsReturnValue bool
50IsInlFormal bool
51StackOffset int32
52// This package can't use the ssa package, so it can't mention ssa.FuncDebug,
53// so indirect through a closure.
54PutLocationList func(listSym, startPC Sym)
55Scope int32
56Type Sym
57DeclFile string
58DeclLine uint
59DeclCol uint
60InlIndex int32 // subtract 1 to form real index into InlTree
61ChildIndex int32 // child DIE index in abstract function
62IsInAbstract 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.
71type Scope struct {
72Parent int32
73Ranges []Range
74Vars []*Var
75}
76
77// A Range represents a half-open interval [Start, End).
78type Range struct {
79Start, 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.
84type FnState struct {
85Name string
86Importpath string
87Info Sym
88Filesym Sym
89Loc Sym
90Ranges Sym
91Absfn Sym
92StartPC Sym
93Size int64
94External bool
95Scopes []Scope
96InlCalls InlCalls
97UseBASEntries bool
98}
99
100func EnableLogging(doit bool) {
101logDwarf = doit
102}
103
104// UnifyRanges merges the list of ranges of c into the list of ranges of s
105func (s *Scope) UnifyRanges(c *Scope) {
106out := make([]Range, 0, len(s.Ranges)+len(c.Ranges))
107
108i, j := 0, 0
109for {
110var cur Range
111if i < len(s.Ranges) && j < len(c.Ranges) {
112if s.Ranges[i].Start < c.Ranges[j].Start {
113cur = s.Ranges[i]
114i++
115} else {
116cur = c.Ranges[j]
117j++
118}
119} else if i < len(s.Ranges) {
120cur = s.Ranges[i]
121i++
122} else if j < len(c.Ranges) {
123cur = c.Ranges[j]
124j++
125} else {
126break
127}
128
129if n := len(out); n > 0 && cur.Start <= out[n-1].End {
130out[n-1].End = cur.End
131} else {
132out = append(out, cur)
133}
134}
135
136s.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.
141func (s *Scope) AppendRange(r Range) {
142if r.End <= r.Start {
143return
144}
145i := len(s.Ranges)
146if i > 0 && s.Ranges[i-1].End == r.Start {
147s.Ranges[i-1].End = r.End
148return
149}
150s.Ranges = append(s.Ranges, r)
151}
152
153type InlCalls struct {
154Calls []InlCall
155}
156
157type InlCall struct {
158// index into ctx.InlTree describing the call inlined here
159InlIndex int
160
161// Symbol of file containing inlined call site (really *obj.LSym).
162CallFile Sym
163
164// Line number of inlined call site.
165CallLine uint32
166
167// Dwarf abstract subroutine symbol (really *obj.LSym).
168AbsFunSym Sym
169
170// Indices of child inlines within Calls array above.
171Children []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.
175InlVars []*Var
176
177// PC ranges for this inlined call.
178Ranges []Range
179
180// Root call (not a child of some other call).
181Root bool
182}
183
184// A Context specifies how to add data to a Sym.
185type Context interface {
186PtrSize() int
187AddInt(s Sym, size int, i int64)
188AddBytes(s Sym, b []byte)
189AddAddress(s Sym, t interface{}, ofs int64)
190AddCURelativeAddress(s Sym, t interface{}, ofs int64)
191AddSectionOffset(s Sym, size int, t interface{}, ofs int64)
192AddDWARFAddrSectionOffset(s Sym, t interface{}, ofs int64)
193CurrentOffset(s Sym) int64
194RecordDclReference(from Sym, to Sym, dclIdx int, inlIndex int)
195RecordChildDieOffsets(s Sym, vars []*Var, offsets []int32)
196AddString(s Sym, v string)
197AddFileRef(s Sym, f interface{})
198Logf(format string, args ...interface{})
199}
200
201// AppendUleb128 appends v to b using DWARF's unsigned LEB128 encoding.
202func AppendUleb128(b []byte, v uint64) []byte {
203for {
204c := uint8(v & 0x7f)
205v >>= 7
206if v != 0 {
207c |= 0x80
208}
209b = append(b, c)
210if c&0x80 == 0 {
211break
212}
213}
214return b
215}
216
217// AppendSleb128 appends v to b using DWARF's signed LEB128 encoding.
218func AppendSleb128(b []byte, v int64) []byte {
219for {
220c := uint8(v & 0x7f)
221s := uint8(v & 0x40)
222v >>= 7
223if (v != -1 || s == 0) && (v != 0 || s != 0) {
224c |= 0x80
225}
226b = append(b, c)
227if c&0x80 == 0 {
228break
229}
230}
231return b
232}
233
234// sevenbits contains all unsigned seven bit numbers, indexed by their value.
235var sevenbits = [...]byte{
2360x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
2370x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
2380x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
2390x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
2400x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
2410x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
2420x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
2430x70, 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.
248func sevenBitU(v int64) []byte {
249if uint64(v) < uint64(len(sevenbits)) {
250return sevenbits[v : v+1]
251}
252return 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.
257func sevenBitS(v int64) []byte {
258if uint64(v) <= 63 {
259return sevenbits[v : v+1]
260}
261if uint64(-v) <= 64 {
262return sevenbits[128+v : 128+v+1]
263}
264return nil
265}
266
267// Uleb128put appends v to s using DWARF's unsigned LEB128 encoding.
268func Uleb128put(ctxt Context, s Sym, v int64) {
269b := sevenBitU(v)
270if b == nil {
271var encbuf [20]byte
272b = AppendUleb128(encbuf[:0], uint64(v))
273}
274ctxt.AddBytes(s, b)
275}
276
277// Sleb128put appends v to s using DWARF's signed LEB128 encoding.
278func Sleb128put(ctxt Context, s Sym, v int64) {
279b := sevenBitS(v)
280if b == nil {
281var encbuf [20]byte
282b = AppendSleb128(encbuf[:0], v)
283}
284ctxt.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*/
295type dwAttrForm struct {
296attr uint16
297form uint8
298}
299
300// Go-specific type attributes.
301const (
302DW_AT_go_kind = 0x2900
303DW_AT_go_key = 0x2901
304DW_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.
307DW_AT_go_embedded_field = 0x2903
308DW_AT_go_runtime_type = 0x2904
309
310DW_AT_go_package_name = 0x2905 // Attribute for DW_TAG_compile_unit
311
312DW_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
318const (
319DW_ABRV_NULL = iota
320DW_ABRV_COMPUNIT
321DW_ABRV_COMPUNIT_TEXTLESS
322DW_ABRV_FUNCTION
323DW_ABRV_FUNCTION_ABSTRACT
324DW_ABRV_FUNCTION_CONCRETE
325DW_ABRV_INLINED_SUBROUTINE
326DW_ABRV_INLINED_SUBROUTINE_RANGES
327DW_ABRV_VARIABLE
328DW_ABRV_INT_CONSTANT
329DW_ABRV_AUTO
330DW_ABRV_AUTO_LOCLIST
331DW_ABRV_AUTO_ABSTRACT
332DW_ABRV_AUTO_CONCRETE
333DW_ABRV_AUTO_CONCRETE_LOCLIST
334DW_ABRV_PARAM
335DW_ABRV_PARAM_LOCLIST
336DW_ABRV_PARAM_ABSTRACT
337DW_ABRV_PARAM_CONCRETE
338DW_ABRV_PARAM_CONCRETE_LOCLIST
339DW_ABRV_LEXICAL_BLOCK_RANGES
340DW_ABRV_LEXICAL_BLOCK_SIMPLE
341DW_ABRV_STRUCTFIELD
342DW_ABRV_FUNCTYPEPARAM
343DW_ABRV_DOTDOTDOT
344DW_ABRV_ARRAYRANGE
345DW_ABRV_NULLTYPE
346DW_ABRV_BASETYPE
347DW_ABRV_ARRAYTYPE
348DW_ABRV_CHANTYPE
349DW_ABRV_FUNCTYPE
350DW_ABRV_IFACETYPE
351DW_ABRV_MAPTYPE
352DW_ABRV_PTRTYPE
353DW_ABRV_BARE_PTRTYPE // only for void*, no DW_AT_type attr to please gdb 6.
354DW_ABRV_SLICETYPE
355DW_ABRV_STRINGTYPE
356DW_ABRV_STRUCTTYPE
357DW_ABRV_TYPEDECL
358DW_NABRV
359)
360
361type dwAbbrev struct {
362tag uint8
363children uint8
364attr []dwAttrForm
365}
366
367var 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.
375func expandPseudoForm(form uint8) uint8 {
376// Is this a pseudo-form?
377if form != DW_FORM_udata_pseudo {
378return form
379}
380expandedForm := DW_FORM_udata
381if objabi.GOOS == "darwin" {
382expandedForm = DW_FORM_data4
383}
384return uint8(expandedForm)
385}
386
387// Abbrevs() returns the finalized abbrev array for the platform,
388// expanding any DW_FORM pseudo-ops to real values.
389func Abbrevs() []dwAbbrev {
390if abbrevsFinalized {
391return abbrevs[:]
392}
393for i := 1; i < DW_NABRV; i++ {
394for j := 0; j < len(abbrevs[i].attr); j++ {
395abbrevs[i].attr[j].form = expandPseudoForm(abbrevs[i].attr[j].form)
396}
397}
398abbrevsFinalized = true
399return 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
406var abbrevs = [DW_NABRV]dwAbbrev{
407/* The mandatory DW_ABRV_NULL entry. */
408{0, 0, []dwAttrForm{}},
409
410/* COMPUNIT */
411{
412DW_TAG_compile_unit,
413DW_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{
428DW_TAG_compile_unit,
429DW_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{
441DW_TAG_subprogram,
442DW_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{
455DW_TAG_subprogram,
456DW_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{
466DW_TAG_subprogram,
467DW_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{
478DW_TAG_inlined_subroutine,
479DW_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{
491DW_TAG_inlined_subroutine,
492DW_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{
503DW_TAG_variable,
504DW_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{
515DW_TAG_constant,
516DW_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{
526DW_TAG_variable,
527DW_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{
538DW_TAG_variable,
539DW_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{
550DW_TAG_variable,
551DW_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{
561DW_TAG_variable,
562DW_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{
571DW_TAG_variable,
572DW_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{
581DW_TAG_formal_parameter,
582DW_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{
594DW_TAG_formal_parameter,
595DW_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{
607DW_TAG_formal_parameter,
608DW_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{
618DW_TAG_formal_parameter,
619DW_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{
628DW_TAG_formal_parameter,
629DW_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{
638DW_TAG_lexical_block,
639DW_CHILDREN_yes,
640[]dwAttrForm{
641{DW_AT_ranges, DW_FORM_sec_offset},
642},
643},
644
645/* LEXICAL_BLOCK_SIMPLE */
646{
647DW_TAG_lexical_block,
648DW_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{
657DW_TAG_member,
658DW_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{
669DW_TAG_formal_parameter,
670DW_CHILDREN_no,
671
672// No name!
673[]dwAttrForm{
674{DW_AT_type, DW_FORM_ref_addr},
675},
676},
677
678/* DOTDOTDOT */
679{
680DW_TAG_unspecified_parameters,
681DW_CHILDREN_no,
682[]dwAttrForm{},
683},
684
685/* ARRAYRANGE */
686{
687DW_TAG_subrange_type,
688DW_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{
700DW_TAG_unspecified_type,
701DW_CHILDREN_no,
702[]dwAttrForm{
703{DW_AT_name, DW_FORM_string},
704},
705},
706
707/* BASETYPE */
708{
709DW_TAG_base_type,
710DW_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{
723DW_TAG_array_type,
724DW_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{
736DW_TAG_typedef,
737DW_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{
749DW_TAG_subroutine_type,
750DW_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{
761DW_TAG_typedef,
762DW_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{
773DW_TAG_typedef,
774DW_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{
787DW_TAG_pointer_type,
788DW_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{
799DW_TAG_pointer_type,
800DW_CHILDREN_no,
801[]dwAttrForm{
802{DW_AT_name, DW_FORM_string},
803},
804},
805
806/* SLICETYPE */
807{
808DW_TAG_structure_type,
809DW_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{
821DW_TAG_structure_type,
822DW_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{
833DW_TAG_structure_type,
834DW_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{
845DW_TAG_typedef,
846DW_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.
855func GetAbbrev() []byte {
856abbrevs := Abbrevs()
857var buf []byte
858for i := 1; i < DW_NABRV; i++ {
859// See section 7.5.3
860buf = AppendUleb128(buf, uint64(i))
861buf = AppendUleb128(buf, uint64(abbrevs[i].tag))
862buf = append(buf, abbrevs[i].children)
863for _, f := range abbrevs[i].attr {
864buf = AppendUleb128(buf, uint64(f.attr))
865buf = AppendUleb128(buf, uint64(f.form))
866}
867buf = append(buf, 0, 0)
868}
869return 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.
882type DWAttr struct {
883Link *DWAttr
884Atr uint16 // DW_AT_
885Cls uint8 // DW_CLS_
886Value int64
887Data interface{}
888}
889
890// DWDie represents a DWARF debug info entry.
891type DWDie struct {
892Abbrev int
893Link *DWDie
894Child *DWDie
895Attr *DWAttr
896Sym Sym
897}
898
899func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, data interface{}) error {
900switch form {
901case DW_FORM_addr: // address
902// Allow nil addresses for DW_AT_go_runtime_type.
903if data == nil && value == 0 {
904ctxt.AddInt(s, ctxt.PtrSize(), 0)
905break
906}
907if cls == DW_CLS_GO_TYPEREF {
908ctxt.AddSectionOffset(s, ctxt.PtrSize(), data, value)
909break
910}
911ctxt.AddAddress(s, data, value)
912
913case DW_FORM_block1: // block
914if cls == DW_CLS_ADDRESS {
915ctxt.AddInt(s, 1, int64(1+ctxt.PtrSize()))
916ctxt.AddInt(s, 1, DW_OP_addr)
917ctxt.AddAddress(s, data, 0)
918break
919}
920
921value &= 0xff
922ctxt.AddInt(s, 1, value)
923p := data.([]byte)[:value]
924ctxt.AddBytes(s, p)
925
926case DW_FORM_block2: // block
927value &= 0xffff
928
929ctxt.AddInt(s, 2, value)
930p := data.([]byte)[:value]
931ctxt.AddBytes(s, p)
932
933case DW_FORM_block4: // block
934value &= 0xffffffff
935
936ctxt.AddInt(s, 4, value)
937p := data.([]byte)[:value]
938ctxt.AddBytes(s, p)
939
940case DW_FORM_block: // block
941Uleb128put(ctxt, s, value)
942
943p := data.([]byte)[:value]
944ctxt.AddBytes(s, p)
945
946case DW_FORM_data1: // constant
947ctxt.AddInt(s, 1, value)
948
949case DW_FORM_data2: // constant
950ctxt.AddInt(s, 2, value)
951
952case DW_FORM_data4: // constant, {line,loclist,mac,rangelist}ptr
953if cls == DW_CLS_PTR { // DW_AT_stmt_list and DW_AT_ranges
954ctxt.AddDWARFAddrSectionOffset(s, data, value)
955break
956}
957ctxt.AddInt(s, 4, value)
958
959case DW_FORM_data8: // constant, {line,loclist,mac,rangelist}ptr
960ctxt.AddInt(s, 8, value)
961
962case DW_FORM_sdata: // constant
963Sleb128put(ctxt, s, value)
964
965case DW_FORM_udata: // constant
966Uleb128put(ctxt, s, value)
967
968case DW_FORM_string: // string
969str := data.(string)
970ctxt.AddString(s, str)
971// TODO(ribrdb): verify padded strings are never used and remove this
972for i := int64(len(str)); i < value; i++ {
973ctxt.AddInt(s, 1, 0)
974}
975
976case DW_FORM_flag: // flag
977if value != 0 {
978ctxt.AddInt(s, 1, 1)
979} else {
980ctxt.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.
985case DW_FORM_ref_addr: // reference to a DIE in the .info section
986fallthrough
987case DW_FORM_sec_offset: // offset into a DWARF section other than .info
988if data == nil {
989return fmt.Errorf("dwarf: null reference in %d", abbrev)
990}
991ctxt.AddDWARFAddrSectionOffset(s, data, value)
992
993case DW_FORM_ref1, // reference within the compilation unit
994DW_FORM_ref2, // reference
995DW_FORM_ref4, // reference
996DW_FORM_ref8, // reference
997DW_FORM_ref_udata, // reference
998
999DW_FORM_strp, // string
1000DW_FORM_indirect: // (see Section 7.5.3)
1001fallthrough
1002default:
1003return fmt.Errorf("dwarf: unsupported attribute form %d / class %d", form, cls)
1004}
1005return 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.
1012func PutAttrs(ctxt Context, s Sym, abbrev int, attr *DWAttr) {
1013abbrevs := Abbrevs()
1014Outer:
1015for _, f := range abbrevs[abbrev].attr {
1016for ap := attr; ap != nil; ap = ap.Link {
1017if ap.Atr == f.attr {
1018putattr(ctxt, s, abbrev, int(f.form), int(ap.Cls), ap.Value, ap.Data)
1019continue Outer
1020}
1021}
1022
1023putattr(ctxt, s, abbrev, int(f.form), 0, 0, nil)
1024}
1025}
1026
1027// HasChildren reports whether 'die' uses an abbrev that supports children.
1028func HasChildren(die *DWDie) bool {
1029abbrevs := Abbrevs()
1030return abbrevs[die.Abbrev].children != 0
1031}
1032
1033// PutIntConst writes a DIE for an integer constant
1034func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) {
1035Uleb128put(ctxt, info, DW_ABRV_INT_CONSTANT)
1036putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
1037putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ)
1038putattr(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).
1044func PutBasedRanges(ctxt Context, sym Sym, ranges []Range) {
1045ps := ctxt.PtrSize()
1046// Write ranges.
1047for _, r := range ranges {
1048ctxt.AddInt(sym, ps, r.Start)
1049ctxt.AddInt(sym, ps, r.End)
1050}
1051// Write trailer.
1052ctxt.AddInt(sym, ps, 0)
1053ctxt.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.
1058func (s *FnState) PutRanges(ctxt Context, ranges []Range) {
1059ps := ctxt.PtrSize()
1060sym, base := s.Ranges, s.StartPC
1061
1062if 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
1065ctxt.AddInt(sym, ps, -1)
1066ctxt.AddAddress(sym, base, 0)
1067PutBasedRanges(ctxt, sym, ranges)
1068return
1069}
1070
1071// Write ranges full of relocations
1072for _, r := range ranges {
1073ctxt.AddCURelativeAddress(sym, base, r.Start)
1074ctxt.AddCURelativeAddress(sym, base, r.End)
1075}
1076// Write trailer.
1077ctxt.AddInt(sym, ps, 0)
1078ctxt.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.
1084func isEmptyInlinedCall(slot int, calls *InlCalls) bool {
1085ic := &calls.Calls[slot]
1086if ic.InlIndex == -2 {
1087return true
1088}
1089live := false
1090for _, k := range ic.Children {
1091if !isEmptyInlinedCall(k, calls) {
1092live = true
1093}
1094}
1095if len(ic.Ranges) > 0 {
1096live = true
1097}
1098if !live {
1099ic.InlIndex = -2
1100}
1101return !live
1102}
1103
1104// Slot -1: return top-level inlines
1105// Slot >= 0: return children of that slot
1106func inlChildren(slot int, calls *InlCalls) []int {
1107var kids []int
1108if slot != -1 {
1109for _, k := range calls.Calls[slot].Children {
1110if !isEmptyInlinedCall(k, calls) {
1111kids = append(kids, k)
1112}
1113}
1114} else {
1115for k := 0; k < len(calls.Calls); k += 1 {
1116if calls.Calls[k].Root && !isEmptyInlinedCall(k, calls) {
1117kids = append(kids, k)
1118}
1119}
1120}
1121return kids
1122}
1123
1124func inlinedVarTable(inlcalls *InlCalls) map[*Var]bool {
1125vars := make(map[*Var]bool)
1126for _, ic := range inlcalls.Calls {
1127for _, v := range ic.InlVars {
1128vars[v] = true
1129}
1130}
1131return 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.
1140func putPrunedScopes(ctxt Context, s *FnState, fnabbrev int) error {
1141if len(s.Scopes) == 0 {
1142return nil
1143}
1144scopes := make([]Scope, len(s.Scopes), len(s.Scopes))
1145pvars := inlinedVarTable(&s.InlCalls)
1146for k, s := range s.Scopes {
1147var pruned Scope = Scope{Parent: s.Parent, Ranges: s.Ranges}
1148for i := 0; i < len(s.Vars); i++ {
1149_, found := pvars[s.Vars[i]]
1150if !found {
1151pruned.Vars = append(pruned.Vars, s.Vars[i])
1152}
1153}
1154sort.Sort(byChildIndex(pruned.Vars))
1155scopes[k] = pruned
1156}
1157var encbuf [20]byte
1158if putscope(ctxt, s, scopes, 0, fnabbrev, encbuf[:0]) < int32(len(scopes)) {
1159return errors.New("multiple toplevel scopes")
1160}
1161return 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).
1171func PutAbstractFunc(ctxt Context, s *FnState) error {
1172
1173if logDwarf {
1174ctxt.Logf("PutAbstractFunc(%v)\n", s.Absfn)
1175}
1176
1177abbrev := DW_ABRV_FUNCTION_ABSTRACT
1178Uleb128put(ctxt, s.Absfn, int64(abbrev))
1179
1180fullname := s.Name
1181if 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).
1189fullname = objabi.PathToPrefix(s.Importpath) + "." + s.Name[3:]
1190}
1191putattr(ctxt, s.Absfn, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(fullname)), fullname)
1192
1193// DW_AT_inlined value
1194putattr(ctxt, s.Absfn, abbrev, DW_FORM_data1, DW_CLS_CONSTANT, int64(DW_INL_inlined), nil)
1195
1196var ev int64
1197if s.External {
1198ev = 1
1199}
1200putattr(ctxt, s.Absfn, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
1201
1202// Child variables (may be empty)
1203var 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.
1207var offsets []int32
1208
1209// Scopes/vars
1210if 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.
1214pvars := inlinedVarTable(&s.InlCalls)
1215for _, scope := range s.Scopes {
1216for i := 0; i < len(scope.Vars); i++ {
1217_, found := pvars[scope.Vars[i]]
1218if found || !scope.Vars[i].IsInAbstract {
1219continue
1220}
1221flattened = append(flattened, scope.Vars[i])
1222}
1223}
1224if len(flattened) > 0 {
1225sort.Sort(byChildIndex(flattened))
1226
1227if logDwarf {
1228ctxt.Logf("putAbstractScope(%v): vars:", s.Info)
1229for i, v := range flattened {
1230ctxt.Logf(" %d:%s", i, v.Name)
1231}
1232ctxt.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.
1238for _, v := range flattened {
1239offsets = append(offsets, int32(ctxt.CurrentOffset(s.Absfn)))
1240putAbstractVar(ctxt, s.Absfn, v)
1241}
1242}
1243}
1244ctxt.RecordChildDieOffsets(s.Absfn, flattened, offsets)
1245
1246Uleb128put(ctxt, s.Absfn, 0)
1247return 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.
1255func PutInlinedFunc(ctxt Context, s *FnState, callersym Sym, callIdx int) error {
1256ic := s.InlCalls.Calls[callIdx]
1257callee := ic.AbsFunSym
1258
1259abbrev := DW_ABRV_INLINED_SUBROUTINE_RANGES
1260if len(ic.Ranges) == 1 {
1261abbrev = DW_ABRV_INLINED_SUBROUTINE
1262}
1263Uleb128put(ctxt, s.Info, int64(abbrev))
1264
1265if logDwarf {
1266ctxt.Logf("PutInlinedFunc(caller=%v,callee=%v,abbrev=%d)\n", callersym, callee, abbrev)
1267}
1268
1269// Abstract origin.
1270putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, callee)
1271
1272if abbrev == DW_ABRV_INLINED_SUBROUTINE_RANGES {
1273putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, s.Ranges.Length(ctxt), s.Ranges)
1274s.PutRanges(ctxt, ic.Ranges)
1275} else {
1276st := ic.Ranges[0].Start
1277en := ic.Ranges[0].End
1278putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, st, s.StartPC)
1279putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, en, s.StartPC)
1280}
1281
1282// Emit call file, line attrs.
1283ctxt.AddFileRef(s.Info, ic.CallFile)
1284form := int(expandPseudoForm(DW_FORM_udata_pseudo))
1285putattr(ctxt, s.Info, abbrev, form, DW_CLS_CONSTANT, int64(ic.CallLine), nil)
1286
1287// Variables associated with this inlined routine instance.
1288vars := ic.InlVars
1289sort.Sort(byChildIndex(vars))
1290inlIndex := ic.InlIndex
1291var encbuf [20]byte
1292for _, v := range vars {
1293if !v.IsInAbstract {
1294continue
1295}
1296putvar(ctxt, s, v, callee, abbrev, inlIndex, encbuf[:0])
1297}
1298
1299// Children of this inline.
1300for _, sib := range inlChildren(callIdx, &s.InlCalls) {
1301absfn := s.InlCalls.Calls[sib].AbsFunSym
1302err := PutInlinedFunc(ctxt, s, absfn, sib)
1303if err != nil {
1304return err
1305}
1306}
1307
1308Uleb128put(ctxt, s.Info, 0)
1309return 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).
1319func PutConcreteFunc(ctxt Context, s *FnState) error {
1320if logDwarf {
1321ctxt.Logf("PutConcreteFunc(%v)\n", s.Info)
1322}
1323abbrev := DW_ABRV_FUNCTION_CONCRETE
1324Uleb128put(ctxt, s.Info, int64(abbrev))
1325
1326// Abstract origin.
1327putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, s.Absfn)
1328
1329// Start/end PC.
1330putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, 0, s.StartPC)
1331putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, s.Size, s.StartPC)
1332
1333// cfa / frame base
1334putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
1335
1336// Scopes
1337if err := putPrunedScopes(ctxt, s, abbrev); err != nil {
1338return err
1339}
1340
1341// Inlined subroutines.
1342for _, sib := range inlChildren(-1, &s.InlCalls) {
1343absfn := s.InlCalls.Calls[sib].AbsFunSym
1344err := PutInlinedFunc(ctxt, s, absfn, sib)
1345if err != nil {
1346return err
1347}
1348}
1349
1350Uleb128put(ctxt, s.Info, 0)
1351return 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).
1359func PutDefaultFunc(ctxt Context, s *FnState) error {
1360if logDwarf {
1361ctxt.Logf("PutDefaultFunc(%v)\n", s.Info)
1362}
1363abbrev := DW_ABRV_FUNCTION
1364Uleb128put(ctxt, s.Info, int64(abbrev))
1365
1366// Expand '"".' to import path.
1367name := s.Name
1368if s.Importpath != "" {
1369name = strings.Replace(name, "\"\".", objabi.PathToPrefix(s.Importpath)+".", -1)
1370}
1371
1372putattr(ctxt, s.Info, DW_ABRV_FUNCTION, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
1373putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, 0, s.StartPC)
1374putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, s.Size, s.StartPC)
1375putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
1376ctxt.AddFileRef(s.Info, s.Filesym)
1377
1378var ev int64
1379if s.External {
1380ev = 1
1381}
1382putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
1383
1384// Scopes
1385if err := putPrunedScopes(ctxt, s, abbrev); err != nil {
1386return err
1387}
1388
1389// Inlined subroutines.
1390for _, sib := range inlChildren(-1, &s.InlCalls) {
1391absfn := s.InlCalls.Calls[sib].AbsFunSym
1392err := PutInlinedFunc(ctxt, s, absfn, sib)
1393if err != nil {
1394return err
1395}
1396}
1397
1398Uleb128put(ctxt, s.Info, 0)
1399return nil
1400}
1401
1402func putscope(ctxt Context, s *FnState, scopes []Scope, curscope int32, fnabbrev int, encbuf []byte) int32 {
1403
1404if logDwarf {
1405ctxt.Logf("putscope(%v,%d): vars:", s.Info, curscope)
1406for i, v := range scopes[curscope].Vars {
1407ctxt.Logf(" %d:%d:%s", i, v.ChildIndex, v.Name)
1408}
1409ctxt.Logf("\n")
1410}
1411
1412for _, v := range scopes[curscope].Vars {
1413putvar(ctxt, s, v, s.Absfn, fnabbrev, -1, encbuf)
1414}
1415this := curscope
1416curscope++
1417for curscope < int32(len(scopes)) {
1418scope := scopes[curscope]
1419if scope.Parent != this {
1420return curscope
1421}
1422
1423if len(scopes[curscope].Vars) == 0 {
1424curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf)
1425continue
1426}
1427
1428if len(scope.Ranges) == 1 {
1429Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE)
1430putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].Start, s.StartPC)
1431putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].End, s.StartPC)
1432} else {
1433Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES)
1434putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_RANGES, DW_FORM_sec_offset, DW_CLS_PTR, s.Ranges.Length(ctxt), s.Ranges)
1435
1436s.PutRanges(ctxt, scope.Ranges)
1437}
1438
1439curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf)
1440
1441Uleb128put(ctxt, s.Info, 0)
1442}
1443return curscope
1444}
1445
1446// Given a default var abbrev code, select corresponding concrete code.
1447func concreteVarAbbrev(varAbbrev int) int {
1448switch varAbbrev {
1449case DW_ABRV_AUTO:
1450return DW_ABRV_AUTO_CONCRETE
1451case DW_ABRV_PARAM:
1452return DW_ABRV_PARAM_CONCRETE
1453case DW_ABRV_AUTO_LOCLIST:
1454return DW_ABRV_AUTO_CONCRETE_LOCLIST
1455case DW_ABRV_PARAM_LOCLIST:
1456return DW_ABRV_PARAM_CONCRETE_LOCLIST
1457default:
1458panic("should never happen")
1459}
1460}
1461
1462// Pick the correct abbrev code for variable or parameter DIE.
1463func determineVarAbbrev(v *Var, fnabbrev int) (int, bool, bool) {
1464abbrev := 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.
1468missing := false
1469switch {
1470case abbrev == DW_ABRV_AUTO_LOCLIST && v.PutLocationList == nil:
1471missing = true
1472abbrev = DW_ABRV_AUTO
1473case abbrev == DW_ABRV_PARAM_LOCLIST && v.PutLocationList == nil:
1474missing = true
1475abbrev = DW_ABRV_PARAM
1476}
1477
1478// Determine whether to use a concrete variable or regular variable DIE.
1479concrete := true
1480switch fnabbrev {
1481case DW_ABRV_FUNCTION:
1482concrete = false
1483break
1484case 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.
1488if !v.IsInAbstract {
1489concrete = false
1490}
1491case DW_ABRV_INLINED_SUBROUTINE, DW_ABRV_INLINED_SUBROUTINE_RANGES:
1492default:
1493panic("should never happen")
1494}
1495
1496// Select proper abbrev based on concrete/non-concrete
1497if concrete {
1498abbrev = concreteVarAbbrev(abbrev)
1499}
1500
1501return abbrev, missing, concrete
1502}
1503
1504func abbrevUsesLoclist(abbrev int) bool {
1505switch abbrev {
1506case DW_ABRV_AUTO_LOCLIST, DW_ABRV_AUTO_CONCRETE_LOCLIST,
1507DW_ABRV_PARAM_LOCLIST, DW_ABRV_PARAM_CONCRETE_LOCLIST:
1508return true
1509default:
1510return false
1511}
1512}
1513
1514// Emit DWARF attributes for a variable belonging to an 'abstract' subprogram.
1515func putAbstractVar(ctxt Context, info Sym, v *Var) {
1516// Remap abbrev
1517abbrev := v.Abbrev
1518switch abbrev {
1519case DW_ABRV_AUTO, DW_ABRV_AUTO_LOCLIST:
1520abbrev = DW_ABRV_AUTO_ABSTRACT
1521case DW_ABRV_PARAM, DW_ABRV_PARAM_LOCLIST:
1522abbrev = DW_ABRV_PARAM_ABSTRACT
1523}
1524
1525Uleb128put(ctxt, info, int64(abbrev))
1526putattr(ctxt, info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(v.Name)), v.Name)
1527
1528// Isreturn attribute if this is a param
1529if abbrev == DW_ABRV_PARAM_ABSTRACT {
1530var isReturn int64
1531if v.IsReturnValue {
1532isReturn = 1
1533}
1534putattr(ctxt, info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil)
1535}
1536
1537// Line
1538if abbrev != DW_ABRV_PARAM_ABSTRACT {
1539// See issue 23374 for more on why decl line is skipped for abs params.
1540putattr(ctxt, info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil)
1541}
1542
1543// Type
1544putattr(ctxt, info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
1545
1546// Var has no children => no terminator
1547}
1548
1549func putvar(ctxt Context, s *FnState, v *Var, absfn Sym, fnabbrev, inlIndex int, encbuf []byte) {
1550// Remap abbrev according to parent DIE abbrev
1551abbrev, missing, concrete := determineVarAbbrev(v, fnabbrev)
1552
1553Uleb128put(ctxt, s.Info, int64(abbrev))
1554
1555// Abstract origin for concrete / inlined case
1556if 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.
1561putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, absfn)
1562ctxt.RecordDclReference(s.Info, absfn, int(v.ChildIndex), inlIndex)
1563} else {
1564// Var name, line for abstract and default cases
1565n := v.Name
1566putattr(ctxt, s.Info, abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n)
1567if abbrev == DW_ABRV_PARAM || abbrev == DW_ABRV_PARAM_LOCLIST || abbrev == DW_ABRV_PARAM_ABSTRACT {
1568var isReturn int64
1569if v.IsReturnValue {
1570isReturn = 1
1571}
1572putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil)
1573}
1574putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil)
1575putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
1576}
1577
1578if abbrevUsesLoclist(abbrev) {
1579putattr(ctxt, s.Info, abbrev, DW_FORM_sec_offset, DW_CLS_PTR, s.Loc.Length(ctxt), s.Loc)
1580v.PutLocationList(s.Loc, s.StartPC)
1581} else {
1582loc := encbuf[:0]
1583switch {
1584case missing:
1585break // no location
1586case v.StackOffset == 0:
1587loc = append(loc, DW_OP_call_frame_cfa)
1588default:
1589loc = append(loc, DW_OP_fbreg)
1590loc = AppendSleb128(loc, int64(v.StackOffset))
1591}
1592putattr(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.
1600type VarsByOffset []*Var
1601
1602func (s VarsByOffset) Len() int { return len(s) }
1603func (s VarsByOffset) Less(i, j int) bool { return s[i].StackOffset < s[j].StackOffset }
1604func (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.
1607type byChildIndex []*Var
1608
1609func (s byChildIndex) Len() int { return len(s) }
1610func (s byChildIndex) Less(i, j int) bool { return s[i].ChildIndex < s[j].ChildIndex }
1611func (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.
1617func IsDWARFEnabledOnAIXLd(extld string) (bool, error) {
1618out, err := exec.Command(extld, "-Wl,-V").CombinedOutput()
1619if 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
1623if !bytes.Contains(out, []byte("0711-317")) {
1624return 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// ...
1630out = bytes.TrimPrefix(out, []byte("/usr/bin/ld: LD "))
1631vers := string(bytes.Split(out, []byte("("))[0])
1632subvers := strings.Split(vers, ".")
1633if len(subvers) != 3 {
1634return false, fmt.Errorf("cannot parse %s -Wl,-V (%s): %v\n", extld, out, err)
1635}
1636if v, err := strconv.Atoi(subvers[0]); err != nil || v < 7 {
1637return false, nil
1638} else if v > 7 {
1639return true, nil
1640}
1641if v, err := strconv.Atoi(subvers[1]); err != nil || v < 2 {
1642return false, nil
1643} else if v > 2 {
1644return true, nil
1645}
1646if v, err := strconv.Atoi(subvers[2]); err != nil || v < 2 {
1647return false, nil
1648}
1649return true, nil
1650}
1651