diff options
author | Sergei Azovskov <lastg@fb.com> | 2018-09-14 15:09:59 +0100 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2018-09-14 15:10:44 +0100 |
commit | c23f057f1753634e2bc0612969470efea6443031 (patch) | |
tree | 75bf13cee0115ae34c3c135d7333183506b1b4fa /compiler/nativeGen | |
parent | 64c54fff2d6534e1229359a8d357ec1dc6c21b73 (diff) | |
download | haskell-c23f057f1753634e2bc0612969470efea6443031.tar.gz |
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
Diffstat (limited to 'compiler/nativeGen')
-rw-r--r-- | compiler/nativeGen/X86/Ppr.hs | 69 |
1 files changed, 64 insertions, 5 deletions
diff --git a/compiler/nativeGen/X86/Ppr.hs b/compiler/nativeGen/X86/Ppr.hs index c5fbeb544e..03d4fce794 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] - |