From patchwork Thu Jul 8 08:03:16 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Use DW_OP_const[48]u instead of DW_OP_addr with DW_OP_GNU_push_tls_address Date: Wed, 07 Jul 2010 22:03:16 -0000 From: Jakub Jelinek X-Patchwork-Id: 58225 Message-Id: <20100708080316.GI20208@tyan-ft48-01.lab.bos.redhat.com> To: Richard Henderson , Jason Merrill Cc: gcc-patches@gcc.gnu.org, Tom Tromey , Roland McGrath Hi! Tom reported that using DW_OP_addr for DW_OP_GNU_push_tls_address is wrong - the @dtprel offset is a constant that shouldn't be relocated, while DW_OP_addr is an address that should be relocated by debug info consumer. Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux. Ok for trunk? 2010-07-08 Jakub Jelinek * dwarf2out.c (mem_loc_descriptor): Use DW_OP_const[48]u instead of DW_OP_addr for DW_OP_GNU_push_tls_address operand. (loc_list_from_tree): Likewise. (output_loc_operands): Handle outputting DW_OP_const[48]u with loc->dtprel set. (resolve_addr_in_expr): Handle loc->dtprel like DW_OP_addr. Jakub --- gcc/dwarf2out.c.jj 2010-07-07 14:25:51.000000000 +0200 +++ gcc/dwarf2out.c 2010-07-07 18:02:26.000000000 +0200 @@ -4928,10 +4928,28 @@ output_loc_operands (dw_loc_descr_ref lo dw2_asm_output_data (2, val1->v.val_int, NULL); break; case DW_OP_const4u: + if (loc->dtprel) + { + gcc_assert (targetm.asm_out.output_dwarf_dtprel); + targetm.asm_out.output_dwarf_dtprel (asm_out_file, 4, + val1->v.val_addr); + fputc ('\n', asm_out_file); + break; + } + /* FALLTHRU */ case DW_OP_const4s: dw2_asm_output_data (4, val1->v.val_int, NULL); break; case DW_OP_const8u: + if (loc->dtprel) + { + gcc_assert (targetm.asm_out.output_dwarf_dtprel); + targetm.asm_out.output_dwarf_dtprel (asm_out_file, 8, + val1->v.val_addr); + fputc ('\n', asm_out_file); + break; + } + /* FALLTHRU */ case DW_OP_const8s: gcc_assert (HOST_BITS_PER_WIDE_INT >= 64); dw2_asm_output_data (8, val1->v.val_int, NULL); @@ -13585,7 +13603,11 @@ mem_loc_descriptor (rtx rtl, enum machin if (!targetm.have_tls || !targetm.asm_out.output_dwarf_dtprel) break; - temp = new_loc_descr (DW_OP_addr, 0, 0); + /* We used to emit DW_OP_addr here, but that's wrong, since + DW_OP_addr should be relocated by the debug info consumer, + while DW_OP_GNU_push_tls_address operand should not. */ + temp = new_loc_descr (DWARF2_ADDR_SIZE == 4 + ? DW_OP_const4u : DW_OP_const8u, 0, 0); temp->dw_loc_oprnd1.val_class = dw_val_class_addr; temp->dw_loc_oprnd1.v.val_addr = rtl; temp->dtprel = true; @@ -15070,10 +15092,13 @@ loc_list_from_tree (tree loc, int want_a /* The way DW_OP_GNU_push_tls_address is specified, we can only look up addresses of objects in the current - module. */ + module. We used DW_OP_addr as first op, but that's + wrong, because DW_OP_addr is relocated by the debug + info consumer, while DW_OP_GNU_push_tls_address + operand shouldn't be. */ if (DECL_EXTERNAL (loc) && !targetm.binds_local_p (loc)) return 0; - first_op = DW_OP_addr; + first_op = DWARF2_ADDR_SIZE == 4 ? DW_OP_const4u : DW_OP_const8u; dtprel = true; second_op = DW_OP_GNU_push_tls_address; } @@ -22073,7 +22098,7 @@ static bool resolve_addr_in_expr (dw_loc_descr_ref loc) { for (; loc; loc = loc->dw_loc_next) - if ((loc->dw_loc_opc == DW_OP_addr + if (((loc->dw_loc_opc == DW_OP_addr || loc->dtprel) && resolve_one_addr (&loc->dw_loc_oprnd1.v.val_addr, NULL)) || (loc->dw_loc_opc == DW_OP_implicit_value && loc->dw_loc_oprnd2.val_class == dw_val_class_addr