[commit: ghc] master: Mark code related symbols as @function not @object (c23f057)

git at git.haskell.org git at git.haskell.org
Fri Sep 14 14:11:22 UTC 2018


Repository : ssh://git@git.haskell.org/ghc

On branch  : master
Link       : http://ghc.haskell.org/trac/ghc/changeset/c23f057f1753634e2bc0612969470efea6443031/ghc

>---------------------------------------------------------------

commit c23f057f1753634e2bc0612969470efea6443031
Author: Sergei Azovskov <lastg at fb.com>
Date:   Fri Sep 14 15:09:59 2018 +0100

    Mark code related symbols as @function not @object
    
    Summary:
    This diff is a part of the bigger project which goal is to improve
    common profiling tools support (perf) for GHC binaries.
    
    A similar job was already done and reverted in the past:
     * https://phabricator.haskell.org/rGHCb1f453e16f0ce11a2ab18cc4c350bdcbd36299a6
     * https://phabricator.haskell.org/rGHCf1f3c4f50650110ad0f700d6566a44c515b0548f
    
    Reasoning:
    
    `Perf` and similar tools build in memory symbol table from the .symtab
    section of the ELF file to display human-readable function names instead
    of the addresses in the output. `Perf` uses only two types of symbols:
    `@function` and `@notype` but GHC is not capable to produce any
    `@function` symbols so the `perf` output is pretty useless (All the
    haskell symbols that you can see in `perf` now are `@notype` internal
    symbols extracted by mistake/hack).
    
    The changes:
     * mark code related symbols as @function
     * small hack to mark InfoTable symbols as code if TABLES_NEXT_TO_CODE is true
    
    Limitations:
     * The perf symbolization support is not complete after this patch but
       I'm working on the second patch.
     * Constructor symbols are not supported. To fix that we can issue extra
       local symbols which mark code sections as code and will be only used
       for debug.
    
    Test Plan:
    tests
    any additional ideas?
    
    Perf output on stock ghc 8.4.1:
    ```
         9.78%  FibbSlow  FibbSlow            [.] ckY_info
         9.59%  FibbSlow  FibbSlow            [.] cjqd_info
         7.17%  FibbSlow  FibbSlow            [.] c3sg_info
         6.62%  FibbSlow  FibbSlow            [.] c1X_info
         5.32%  FibbSlow  FibbSlow            [.] cjsX_info
         4.18%  FibbSlow  FibbSlow            [.] s3rN_info
         3.82%  FibbSlow  FibbSlow            [.] c2m_info
         3.68%  FibbSlow  FibbSlow            [.] cjlJ_info
         3.26%  FibbSlow  FibbSlow            [.] c3sb_info
         3.19%  FibbSlow  FibbSlow            [.] cjPQ_info
         3.05%  FibbSlow  FibbSlow            [.] cjQd_info
         2.97%  FibbSlow  FibbSlow            [.] cjAB_info
         2.78%  FibbSlow  FibbSlow            [.] cjzP_info
         2.40%  FibbSlow  FibbSlow            [.] cjOS_info
         2.38%  FibbSlow  FibbSlow            [.] s3rK_info
         2.27%  FibbSlow  FibbSlow            [.] cjq0_info
         2.18%  FibbSlow  FibbSlow            [.] cKQ_info
         2.13%  FibbSlow  FibbSlow            [.] cjSl_info
         1.99%  FibbSlow  FibbSlow            [.] s3rL_info
         1.98%  FibbSlow  FibbSlow            [.] c2cC_info
         1.80%  FibbSlow  FibbSlow            [.] s3rO_info
         1.37%  FibbSlow  FibbSlow            [.] c2f2_info
    ...
    ```
    
    Perf output on patched ghc:
    ```
         7.97%  FibbSlow  FibbSlow            [.] c3rM_info
         6.75%  FibbSlow  FibbSlow            [.] 0x000000000032cfa8
         6.63%  FibbSlow  FibbSlow            [.] cifA_info
         4.98%  FibbSlow  FibbSlow            [.] integerzmgmp_GHCziIntegerziType_eqIntegerzh_info
         4.55%  FibbSlow  FibbSlow            [.] chXn_info
         4.52%  FibbSlow  FibbSlow            [.] c3rH_info
         4.45%  FibbSlow  FibbSlow            [.] chZB_info
         4.04%  FibbSlow  FibbSlow            [.] Main_fibbzuslow_info
         4.03%  FibbSlow  FibbSlow            [.] stg_ap_0_fast
         3.76%  FibbSlow  FibbSlow            [.] chXA_info
         3.67%  FibbSlow  FibbSlow            [.] cifu_info
         3.25%  FibbSlow  FibbSlow            [.] ci4r_info
         2.64%  FibbSlow  FibbSlow            [.] s3rf_info
         2.42%  FibbSlow  FibbSlow            [.] s3rg_info
         2.39%  FibbSlow  FibbSlow            [.] integerzmgmp_GHCziIntegerziType_eqInteger_info
         2.25%  FibbSlow  FibbSlow            [.] integerzmgmp_GHCziIntegerziType_minusInteger_info
         2.17%  FibbSlow  FibbSlow            [.] ghczmprim_GHCziClasses_zeze_info
         2.09%  FibbSlow  FibbSlow            [.] cicc_info
         2.03%  FibbSlow  FibbSlow            [.] 0x0000000000331e15
         2.02%  FibbSlow  FibbSlow            [.] s3ri_info
         1.91%  FibbSlow  FibbSlow            [.] 0x0000000000331bb8
         1.89%  FibbSlow  FibbSlow            [.] ci4N_info
    ...
    ```
    
    Reviewers: simonmar, niteria, bgamari, goldfire
    
    Reviewed By: simonmar, bgamari
    
    Subscribers: lelf, rwbarton, thomie, carter
    
    GHC Trac Issues: #15501
    
    Differential Revision: https://phabricator.haskell.org/D4713


>---------------------------------------------------------------

c23f057f1753634e2bc0612969470efea6443031
 compiler/cmm/CLabel.hs        | 17 ++++++++++-
 compiler/nativeGen/X86/Ppr.hs | 69 +++++++++++++++++++++++++++++++++++++++----
 2 files changed, 80 insertions(+), 6 deletions(-)

diff --git a/compiler/cmm/CLabel.hs b/compiler/cmm/CLabel.hs
index 1ba0d89..12c3357 100644
--- a/compiler/cmm/CLabel.hs
+++ b/compiler/cmm/CLabel.hs
@@ -104,7 +104,9 @@ module CLabel (
         -- * Conversions
         toClosureLbl, toSlowEntryLbl, toEntryLbl, toInfoLbl, hasHaskellName,
 
-        pprCLabel
+        pprCLabel,
+        isInfoTableLabel,
+        isConInfoTableLabel
     ) where
 
 #include "HsVersions.h"
@@ -621,6 +623,19 @@ isSomeRODataLabel (IdLabel _ _ BlockInfoTable) = True
 isSomeRODataLabel (CmmLabel _ _ CmmInfo) = True
 isSomeRODataLabel _lbl = False
 
+-- | Whether label is points to some kind of info table
+isInfoTableLabel :: CLabel -> Bool
+isInfoTableLabel (IdLabel _ _ InfoTable)      = True
+isInfoTableLabel (IdLabel _ _ LocalInfoTable) = True
+isInfoTableLabel (IdLabel _ _ ConInfoTable)   = True
+isInfoTableLabel (IdLabel _ _ BlockInfoTable) = True
+isInfoTableLabel _                            = False
+
+-- | Whether label is points to constructor info table
+isConInfoTableLabel :: CLabel -> Bool
+isConInfoTableLabel (IdLabel _ _ ConInfoTable)   = True
+isConInfoTableLabel _                            = False
+
 -- | Get the label size field from a ForeignLabel
 foreignLabelStdcallInfo :: CLabel -> Maybe Int
 foreignLabelStdcallInfo (ForeignLabel _ info _ _) = info
diff --git a/compiler/nativeGen/X86/Ppr.hs b/compiler/nativeGen/X86/Ppr.hs
index c5fbeb5..03d4fce 100644
--- a/compiler/nativeGen/X86/Ppr.hs
+++ b/compiler/nativeGen/X86/Ppr.hs
@@ -170,16 +170,76 @@ pprGloblDecl lbl
   | not (externallyVisibleCLabel lbl) = empty
   | otherwise = text ".globl " <> ppr lbl
 
-pprTypeAndSizeDecl :: CLabel -> SDoc
-pprTypeAndSizeDecl lbl
+pprLabelType' :: DynFlags -> CLabel -> SDoc
+pprLabelType' dflags lbl =
+  if isCFunctionLabel lbl || functionOkInfoTable then
+    text "@function"
+  else
+    text "@object"
+  where
+    {-
+    NOTE: This is a bit hacky.
+
+    With the `tablesNextToCode` info tables look like this:
+    ```
+      <info table data>
+    label_info:
+      <info table code>
+    ```
+    So actually info table label points exactly to the code and we can mark
+    the label as @function. (This is required to make perf and potentially other
+    tools to work on Haskell binaries).
+    This usually works well but it can cause issues with a linker.
+    A linker uses different algorithms for the relocation depending on
+    the symbol type.For some reason, a linker will generate JUMP_SLOT relocation
+    when constructor info table is referenced from a data section.
+    This only happens with static constructor call so
+    we mark _con_info symbols as `@object` to avoid the issue with relocations.
+
+    @SimonMarlow hack explanation:
+    "The reasoning goes like this:
+
+    * The danger when we mark a symbol as `@function` is that the linker will
+      redirect it to point to the PLT and use a `JUMP_SLOT` relocation when
+      the symbol refers to something outside the current shared object.
+      A PLT / JUMP_SLOT reference only works for symbols that we jump to, not
+      for symbols representing data,, nor for info table symbol references which
+      we expect to point directly to the info table.
+    * GHC generates code that might refer to any info table symbol from the text
+      segment, but that's OK, because those will be explicit GOT references
+      generated by the code generator.
+    * When we refer to info tables from the data segment, it's either
+      * a FUN_STATIC/THUNK_STATIC local to this module
+      * a `con_info` that could be from anywhere
+
+    So, the only info table symbols that we might refer to from the data segment
+    of another shared object are `con_info` symbols, so those are the ones we
+    need to exclude from getting the @function treatment.
+    "
+
+    A good place to check for more
+    https://ghc.haskell.org/trac/ghc/wiki/Commentary/PositionIndependentCode
+
+    Another possible hack is to create an extra local function symbol for
+    every code-like thing to give the needed information for to the tools
+    but mess up with the relocation. https://phabricator.haskell.org/D4730
+    -}
+    functionOkInfoTable = tablesNextToCode dflags &&
+      isInfoTableLabel lbl && not (isConInfoTableLabel lbl)
+
+
+pprTypeDecl :: CLabel -> SDoc
+pprTypeDecl lbl
     = sdocWithPlatform $ \platform ->
       if osElfTarget (platformOS platform) && externallyVisibleCLabel lbl
-      then text ".type " <> ppr lbl <> ptext (sLit ", @object")
+      then
+        sdocWithDynFlags $ \df ->
+          text ".type " <> ppr lbl <> ptext (sLit  ", ") <> pprLabelType' df lbl
       else empty
 
 pprLabel :: CLabel -> SDoc
 pprLabel lbl = pprGloblDecl lbl
-            $$ pprTypeAndSizeDecl lbl
+            $$ pprTypeDecl lbl
             $$ (ppr lbl <> char ':')
 
 {-
@@ -1346,4 +1406,3 @@ pprFormatOpOpCoerce name format1 format2 op1 op2
 pprCondInstr :: LitString -> Cond -> SDoc -> SDoc
 pprCondInstr name cond arg
   = hcat [ char '\t', ptext name, pprCond cond, space, arg]
-



More information about the ghc-commits mailing list