]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: mark wrapper functions with DW_AT_trampoline
authorAlessandro Arzilli <alessandro.arzilli@gmail.com>
Fri, 3 Sep 2021 13:04:52 +0000 (15:04 +0200)
committerThan McIntosh <thanm@google.com>
Wed, 15 Sep 2021 14:17:48 +0000 (14:17 +0000)
Change DWARF generation to tag wrapper functions with the
"DW_AT_trampoline attribute". The intent is that debuggers can pick up
on this attr so as to skip through the wrapper to the eventual target.

DWARF standard allows for a couple of different possible variants of
the trampoline attr; this is the simplest variant (all it tells the
debugger is that the function is a wrapper, doesn't include a
reference to the wrapper routine).

This implementation keys off the WRAPPER LSym attribute, which is set
for method wrappers, ABI wrappers, and a selected set of runtime
assembly routines (ex: "runtime.call32").

Change-Id: Ib53e1bc56c02b86ca3ac5e7da1a541ec262726cf
Reviewed-on: https://go-review.googlesource.com/c/go/+/347352
Reviewed-by: Than McIntosh <thanm@google.com>
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Jeremy Faller <jeremy@golang.org>

src/cmd/internal/dwarf/dwarf.go
src/cmd/internal/obj/dwarf.go

index 4e163db020f959751c7fcc79ae8c9838116013e9..69aafaf986006adaf9e33a3508f54234e967bc70 100644 (file)
@@ -325,8 +325,10 @@ const (
        DW_ABRV_COMPUNIT
        DW_ABRV_COMPUNIT_TEXTLESS
        DW_ABRV_FUNCTION
+       DW_ABRV_WRAPPER
        DW_ABRV_FUNCTION_ABSTRACT
        DW_ABRV_FUNCTION_CONCRETE
+       DW_ABRV_WRAPPER_CONCRETE
        DW_ABRV_INLINED_SUBROUTINE
        DW_ABRV_INLINED_SUBROUTINE_RANGES
        DW_ABRV_VARIABLE
@@ -455,6 +457,19 @@ var abbrevs = [DW_NABRV]dwAbbrev{
                },
        },
 
+       /* WRAPPER */
+       {
+               DW_TAG_subprogram,
+               DW_CHILDREN_yes,
+               []dwAttrForm{
+                       {DW_AT_name, DW_FORM_string},
+                       {DW_AT_low_pc, DW_FORM_addr},
+                       {DW_AT_high_pc, DW_FORM_addr},
+                       {DW_AT_frame_base, DW_FORM_block1},
+                       {DW_AT_trampoline, DW_FORM_flag},
+               },
+       },
+
        /* FUNCTION_ABSTRACT */
        {
                DW_TAG_subprogram,
@@ -478,6 +493,19 @@ var abbrevs = [DW_NABRV]dwAbbrev{
                },
        },
 
+       /* WRAPPER_CONCRETE */
+       {
+               DW_TAG_subprogram,
+               DW_CHILDREN_yes,
+               []dwAttrForm{
+                       {DW_AT_abstract_origin, DW_FORM_ref_addr},
+                       {DW_AT_low_pc, DW_FORM_addr},
+                       {DW_AT_high_pc, DW_FORM_addr},
+                       {DW_AT_frame_base, DW_FORM_block1},
+                       {DW_AT_trampoline, DW_FORM_flag},
+               },
+       },
+
        /* INLINED_SUBROUTINE */
        {
                DW_TAG_inlined_subroutine,
@@ -1329,11 +1357,14 @@ func putInlinedFunc(ctxt Context, s *FnState, callIdx int) error {
 // for the function (which holds location-independent attributes such
 // as name, type), then the remainder of the attributes are specific
 // to this instance (location, frame base, etc).
-func PutConcreteFunc(ctxt Context, s *FnState) error {
+func PutConcreteFunc(ctxt Context, s *FnState, isWrapper bool) error {
        if logDwarf {
                ctxt.Logf("PutConcreteFunc(%v)\n", s.Info)
        }
        abbrev := DW_ABRV_FUNCTION_CONCRETE
+       if isWrapper {
+               abbrev = DW_ABRV_WRAPPER_CONCRETE
+       }
        Uleb128put(ctxt, s.Info, int64(abbrev))
 
        // Abstract origin.
@@ -1346,6 +1377,10 @@ func PutConcreteFunc(ctxt Context, s *FnState) error {
        // cfa / frame base
        putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
 
+       if isWrapper {
+               putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, int64(1), 0)
+       }
+
        // Scopes
        if err := putPrunedScopes(ctxt, s, abbrev); err != nil {
                return err
@@ -1368,11 +1403,14 @@ func PutConcreteFunc(ctxt Context, s *FnState) error {
 // when its containing package was compiled (hence there is no need to
 // emit an abstract version for it to use as a base for inlined
 // routine records).
-func PutDefaultFunc(ctxt Context, s *FnState) error {
+func PutDefaultFunc(ctxt Context, s *FnState, isWrapper bool) error {
        if logDwarf {
                ctxt.Logf("PutDefaultFunc(%v)\n", s.Info)
        }
        abbrev := DW_ABRV_FUNCTION
+       if isWrapper {
+               abbrev = DW_ABRV_WRAPPER
+       }
        Uleb128put(ctxt, s.Info, int64(abbrev))
 
        // Expand '"".' to import path.
@@ -1385,13 +1423,16 @@ func PutDefaultFunc(ctxt Context, s *FnState) error {
        putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, 0, s.StartPC)
        putattr(ctxt, s.Info, abbrev, DW_FORM_addr, DW_CLS_ADDRESS, s.Size, s.StartPC)
        putattr(ctxt, s.Info, abbrev, DW_FORM_block1, DW_CLS_BLOCK, 1, []byte{DW_OP_call_frame_cfa})
-       ctxt.AddFileRef(s.Info, s.Filesym)
-
-       var ev int64
-       if s.External {
-               ev = 1
+       if isWrapper {
+               putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, int64(1), 0)
+       } else {
+               ctxt.AddFileRef(s.Info, s.Filesym)
+               var ev int64
+               if s.External {
+                       ev = 1
+               }
+               putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
        }
-       putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, ev, 0)
 
        // Scopes
        if err := putPrunedScopes(ctxt, s, abbrev); err != nil {
@@ -1489,10 +1530,10 @@ func determineVarAbbrev(v *Var, fnabbrev int) (int, bool, bool) {
        // Determine whether to use a concrete variable or regular variable DIE.
        concrete := true
        switch fnabbrev {
-       case DW_ABRV_FUNCTION:
+       case DW_ABRV_FUNCTION, DW_ABRV_WRAPPER:
                concrete = false
                break
-       case DW_ABRV_FUNCTION_CONCRETE:
+       case DW_ABRV_FUNCTION_CONCRETE, DW_ABRV_WRAPPER_CONCRETE:
                // If we're emitting a concrete subprogram DIE and the variable
                // in question is not part of the corresponding abstract function DIE,
                // then use the default (non-concrete) abbrev for this param.
index 6dd53ffd1215e839b91d8657101e4a44ee9648c7..29e367aa4cc0ef34ac63eb20a22dc85e2e2f4d29 100644 (file)
@@ -378,9 +378,9 @@ func (ctxt *Link) populateDWARF(curfn interface{}, s *LSym, myimportpath string)
                if err != nil {
                        ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err)
                }
-               err = dwarf.PutConcreteFunc(dwctxt, fnstate)
+               err = dwarf.PutConcreteFunc(dwctxt, fnstate, s.Wrapper())
        } else {
-               err = dwarf.PutDefaultFunc(dwctxt, fnstate)
+               err = dwarf.PutDefaultFunc(dwctxt, fnstate, s.Wrapper())
        }
        if err != nil {
                ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err)