dwarf.go raw
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