From 7b0ee5342919908e1a6b91d7c92a530ef45f5824 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Mon, 7 Jul 2014 16:07:24 -0700 Subject: [PATCH] cmd/ld: fix off-by-one in DWARF frame tables The code generating the .debug_frame section emits pairs of "advance PC", "set SP offset" pseudo-instructions. Before the fix, the PC advance comes out before the SP setting, which means the emitted offset for a block is actually the value at the end of the block, which is incorrect for the block itself. The easiest way to fix this problem is to emit the SP offset before the PC advance. One delicate point: the last instruction to come out is now an "advance PC", which means that if there are padding intsructions after the final RET, they will appear to have a non-zero offset. This is odd but harmless because there is no legal way to have a PC in that range, or to put it another way, if you get here the SP is certainly screwed up so getting the wrong (virtual) frame pointer is the least of your worries. LGTM=iant R=rsc, iant, lvd CC=golang-codereviews https://golang.org/cl/112750043 --- src/cmd/ld/dwarf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c index cc77b45cd6..a9f9329932 100644 --- a/src/cmd/ld/dwarf.c +++ b/src/cmd/ld/dwarf.c @@ -1696,6 +1696,9 @@ enum static void putpccfadelta(vlong deltapc, vlong cfa) { + cput(DW_CFA_def_cfa_offset_sf); + sleb128put(cfa / DATAALIGNMENTFACTOR); + if (deltapc < 0x40) { cput(DW_CFA_advance_loc + deltapc); } else if (deltapc < 0x100) { @@ -1708,9 +1711,6 @@ putpccfadelta(vlong deltapc, vlong cfa) cput(DW_CFA_advance_loc4); LPUT(deltapc); } - - cput(DW_CFA_def_cfa_offset_sf); - sleb128put(cfa / DATAALIGNMENTFACTOR); } static void -- 2.48.1