Commit b56d1bad authored by Than McIntosh's avatar Than McIntosh

cmd/compile: emit DWARF call_line attrs with data4 form on iOS

When targeting iOS, change the format (DWARF "form") of the call line
attribute for inlined subroutine DIEs, to work around an apparent bug
in /usr/bin/symbols on Darwin.

[Just for posterity: there is nothing wrong with using DW_FORM_udata
for the call_line attribute form; this is perfectly legal DWARF (and
is in fact recommended by the standard relative to data4, which is
less descriptive and often takes more space). The form switch is there
just to make the Apple tools happy.]

Updates #31459.

Change-Id: Iaf362788a8c6684eea4cde8956c0661b694cecc1
Reviewed-on: https://go-review.googlesource.com/c/go/+/174538
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarDavid Chase <drchase@google.com>
parent b6f59cbc
...@@ -280,10 +280,12 @@ func Sleb128put(ctxt Context, s Sym, v int64) { ...@@ -280,10 +280,12 @@ func Sleb128put(ctxt Context, s Sym, v int64) {
} }
/* /*
* Defining Abbrevs. This is hardcoded, and there will be * Defining Abbrevs. This is hardcoded on a per-platform basis (that is,
* only a handful of them. The DWARF spec places no restriction on * each platform will see a fixed abbrev table for all objects); the number
* the ordering of attributes in the Abbrevs and DIEs, and we will * of abbrev entries is fairly small (compared to C++ objects). The DWARF
* always write them out in the order of declaration in the abbrev. * spec places no restriction on the ordering of attributes in the
* Abbrevs and DIEs, and we will always write them out in the order
* of declaration in the abbrev.
*/ */
type dwAttrForm struct { type dwAttrForm struct {
attr uint16 attr uint16
...@@ -357,6 +359,45 @@ type dwAbbrev struct { ...@@ -357,6 +359,45 @@ type dwAbbrev struct {
attr []dwAttrForm attr []dwAttrForm
} }
var abbrevsFinalized bool
// expandPseudoForm takes an input DW_FORM_xxx value and translates it
// into a platform-appropriate concrete form. Existing concrete/real
// DW_FORM values are left untouched. For the moment the only
// pseudo-form is DW_FORM_udata_pseudo, which gets expanded to
// DW_FORM_data4 on Darwin and DW_FORM_udata everywhere else. See
// issue #31459 for more context.
func expandPseudoForm(form uint8) uint8 {
// Is this a pseudo-form?
if form != DW_FORM_udata_pseudo {
return form
}
expandedForm := DW_FORM_udata
if objabi.GOOS == "darwin" {
expandedForm = DW_FORM_data4
}
return uint8(expandedForm)
}
// Abbrevs() returns the finalized abbrev array for the platform,
// expanding any DW_FORM pseudo-ops to real values.
func Abbrevs() [DW_NABRV]dwAbbrev {
if abbrevsFinalized {
return abbrevs
}
for i := 1; i < DW_NABRV; i++ {
for j := 0; j < len(abbrevs[i].attr); j++ {
abbrevs[i].attr[j].form = expandPseudoForm(abbrevs[i].attr[j].form)
}
}
abbrevsFinalized = true
return abbrevs
}
// abbrevs is a raw table of abbrev entries; it needs to be post-processed
// by the Abbrevs() function above prior to being consumed, to expand
// the 'pseudo-form' entries below to real DWARF form values.
var abbrevs = [DW_NABRV]dwAbbrev{ var abbrevs = [DW_NABRV]dwAbbrev{
/* The mandatory DW_ABRV_NULL entry. */ /* The mandatory DW_ABRV_NULL entry. */
{0, 0, []dwAttrForm{}}, {0, 0, []dwAttrForm{}},
...@@ -436,7 +477,7 @@ var abbrevs = [DW_NABRV]dwAbbrev{ ...@@ -436,7 +477,7 @@ var abbrevs = [DW_NABRV]dwAbbrev{
{DW_AT_low_pc, DW_FORM_addr}, {DW_AT_low_pc, DW_FORM_addr},
{DW_AT_high_pc, DW_FORM_addr}, {DW_AT_high_pc, DW_FORM_addr},
{DW_AT_call_file, DW_FORM_data4}, {DW_AT_call_file, DW_FORM_data4},
{DW_AT_call_line, DW_FORM_udata}, {DW_AT_call_line, DW_FORM_udata_pseudo}, // pseudo-form
}, },
}, },
...@@ -448,7 +489,7 @@ var abbrevs = [DW_NABRV]dwAbbrev{ ...@@ -448,7 +489,7 @@ var abbrevs = [DW_NABRV]dwAbbrev{
{DW_AT_abstract_origin, DW_FORM_ref_addr}, {DW_AT_abstract_origin, DW_FORM_ref_addr},
{DW_AT_ranges, DW_FORM_sec_offset}, {DW_AT_ranges, DW_FORM_sec_offset},
{DW_AT_call_file, DW_FORM_data4}, {DW_AT_call_file, DW_FORM_data4},
{DW_AT_call_line, DW_FORM_udata}, {DW_AT_call_line, DW_FORM_udata_pseudo}, // pseudo-form
}, },
}, },
...@@ -807,6 +848,7 @@ var abbrevs = [DW_NABRV]dwAbbrev{ ...@@ -807,6 +848,7 @@ var abbrevs = [DW_NABRV]dwAbbrev{
// GetAbbrev returns the contents of the .debug_abbrev section. // GetAbbrev returns the contents of the .debug_abbrev section.
func GetAbbrev() []byte { func GetAbbrev() []byte {
abbrevs := Abbrevs()
var buf []byte var buf []byte
for i := 1; i < DW_NABRV; i++ { for i := 1; i < DW_NABRV; i++ {
// See section 7.5.3 // See section 7.5.3
...@@ -963,6 +1005,7 @@ func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, da ...@@ -963,6 +1005,7 @@ func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, da
// Note that we can (and do) add arbitrary attributes to a DIE, but // Note that we can (and do) add arbitrary attributes to a DIE, but
// only the ones actually listed in the Abbrev will be written out. // only the ones actually listed in the Abbrev will be written out.
func PutAttrs(ctxt Context, s Sym, abbrev int, attr *DWAttr) { func PutAttrs(ctxt Context, s Sym, abbrev int, attr *DWAttr) {
abbrevs := Abbrevs()
Outer: Outer:
for _, f := range abbrevs[abbrev].attr { for _, f := range abbrevs[abbrev].attr {
for ap := attr; ap != nil; ap = ap.Link { for ap := attr; ap != nil; ap = ap.Link {
...@@ -978,6 +1021,7 @@ Outer: ...@@ -978,6 +1021,7 @@ Outer:
// HasChildren reports whether 'die' uses an abbrev that supports children. // HasChildren reports whether 'die' uses an abbrev that supports children.
func HasChildren(die *DWDie) bool { func HasChildren(die *DWDie) bool {
abbrevs := Abbrevs()
return abbrevs[die.Abbrev].children != 0 return abbrevs[die.Abbrev].children != 0
} }
...@@ -1232,7 +1276,8 @@ func PutInlinedFunc(ctxt Context, s *FnState, callersym Sym, callIdx int) error ...@@ -1232,7 +1276,8 @@ func PutInlinedFunc(ctxt Context, s *FnState, callersym Sym, callIdx int) error
// Emit call file, line attrs. // Emit call file, line attrs.
ctxt.AddFileRef(s.Info, ic.CallFile) ctxt.AddFileRef(s.Info, ic.CallFile)
putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(ic.CallLine), nil) form := int(expandPseudoForm(DW_FORM_udata_pseudo))
putattr(ctxt, s.Info, abbrev, form, DW_CLS_CONSTANT, int64(ic.CallLine), nil)
// Variables associated with this inlined routine instance. // Variables associated with this inlined routine instance.
vars := ic.InlVars vars := ic.InlVars
......
...@@ -220,6 +220,8 @@ const ( ...@@ -220,6 +220,8 @@ const (
DW_FORM_exprloc = 0x18 // exprloc DW_FORM_exprloc = 0x18 // exprloc
DW_FORM_flag_present = 0x19 // flag DW_FORM_flag_present = 0x19 // flag
DW_FORM_ref_sig8 = 0x20 // reference DW_FORM_ref_sig8 = 0x20 // reference
// Pseudo-form: expanded to data4 on IOS, udata elsewhere.
DW_FORM_udata_pseudo = 0x99
) )
// Table 24 (#operands, notes) // Table 24 (#operands, notes)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment