summaryrefslogtreecommitdiff
path: root/compiler/nativeGen
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/nativeGen')
-rw-r--r--compiler/nativeGen/X86/Ppr.hs69
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]
-