summaryrefslogtreecommitdiff
blob: f02cb238c6b9d40a5d8a580eadb61dcb40ce4e14 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
From 358b508051333882d4099acca8f269e6fb2b7d65 Mon Sep 17 00:00:00 2001
From: Bertram Felgenhauer <int-e@gmx.de>
Date: Thu, 3 May 2018 18:03:53 +0300
Subject: [PATCH] Compute DW_FORM_block length correctly; also fixes #15068

Before this patch, the pprUnwindwExpr function computed the length of
by the following assembly fragment:

	.uleb128 1f-.-1
	<expression data>
1:

That is, to compute the length, it takes the difference of the label 1
and the address of the .uleb128 directive, and subtracts 1.

In #15068 it was reported that `as` from binutils 4.30 has trouble with
evaluating the `.` part of the expression. However, there is actually a
problem with the expression, if the length of the data ever becomes
larger than 128: In that case, the .uleb128 directive will emit more
than 1 byte, and the computed length will be wrong.

The present patch changes the assembly fragment to use two labels,
which fixes both these problems.

	.uleb128 2f-1f
1:
	<expression data>
2:

Test Plan: validate

Reviewers: bgamari, osa1

Reviewed By: bgamari

Subscribers: thomie, carter

GHC Trac Issues: #15068

Differential Revision: https://phabricator.haskell.org/D4654
---
 compiler/nativeGen/Dwarf/Types.hs | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/compiler/nativeGen/Dwarf/Types.hs b/compiler/nativeGen/Dwarf/Types.hs
index 23a2c920e7..579ed0d256 100644
--- a/compiler/nativeGen/Dwarf/Types.hs
+++ b/compiler/nativeGen/Dwarf/Types.hs
@@ -492,9 +492,11 @@ pprUnwindExpr spIsCFA expr
         pprE (UwPlus u1 u2)   = pprE u1 $$ pprE u2 $$ pprByte dW_OP_plus
         pprE (UwMinus u1 u2)  = pprE u1 $$ pprE u2 $$ pprByte dW_OP_minus
         pprE (UwTimes u1 u2)  = pprE u1 $$ pprE u2 $$ pprByte dW_OP_mul
-    in text "\t.uleb128 1f-.-1" $$ -- DW_FORM_block length
+    in text "\t.uleb128 2f-1f" $$ -- DW_FORM_block length
+       -- computed as the difference of the following local labels 2: and 1:
+       text "1:" $$
        pprE expr $$
-       text "1:"
+       text "2:"
 
 -- | Generate code for re-setting the unwind information for a
 -- register to @undefined@
-- 
2.17.0