From patchwork Tue Jun 3 05:03:15 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kyle McMartin X-Patchwork-Id: 31317 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pa0-f71.google.com (mail-pa0-f71.google.com [209.85.220.71]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id F194C203C2 for ; Tue, 3 Jun 2014 05:03:28 +0000 (UTC) Received: by mail-pa0-f71.google.com with SMTP id kx10sf13133334pab.10 for ; Mon, 02 Jun 2014 22:03:28 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:mailing-list:precedence:list-id :list-unsubscribe:list-subscribe:list-archive:list-post:list-help :sender:delivered-to:date:from:to:subject:message-id:mime-version :in-reply-to:user-agent:x-original-sender :x-original-authentication-results:content-type:content-disposition; bh=8fsc3qZGXMAt4gHAnRh4/O3cPLJUZ5CDurYI7UWd/Ag=; b=mAlmZja24V+ob8RlXmw+8J2FXNV8JZ17giBYLIYfeOC3UO6aDfFYAnYEfBKFYFAIzZ 6ll/Ve+yCuDJ9bcw1+62hZ29/cKsaKb5whvuXs/taD1Tawj6X+Y+/xOaOMZ3YOnKiKyv pGS/Nqq7+esR6uaE8AcVLj5X1bVHqukWB1VsHrKAO94VsGkuB+BuO1UhdSQmb1XBxcsH tvi6B/YBT8Yu5kHSQHK8Zx1TmfiIOXGVL2mQEsOJ2UPTxG4uUs6CiaPdvpVi1h1Eh6q3 S0/4X+DAlbC6q9zMVL3TCkNHG818KhmjTJ4QKDJyPLsDwLCbbi8v4a3+yWp6qWyB6RTP leyA== X-Gm-Message-State: ALoCoQmHQVf7DLi2ZU/cwMhDDn87FOiFh2+0s30AeiU0XtP0dtp5UHbxDJ+vACl7HnDdk/xoPhAe X-Received: by 10.66.236.136 with SMTP id uu8mr16264129pac.13.1401771808186; Mon, 02 Jun 2014 22:03:28 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.47.82 with SMTP id l76ls2289345qga.61.gmail; Mon, 02 Jun 2014 22:03:28 -0700 (PDT) X-Received: by 10.220.253.132 with SMTP id na4mr5087277vcb.39.1401771807972; Mon, 02 Jun 2014 22:03:27 -0700 (PDT) Received: from mail-vc0-x22c.google.com (mail-vc0-x22c.google.com [2607:f8b0:400c:c03::22c]) by mx.google.com with ESMTPS id sn13si9293983vdb.86.2014.06.02.22.03.27 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 02 Jun 2014 22:03:27 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 2607:f8b0:400c:c03::22c as permitted sender) client-ip=2607:f8b0:400c:c03::22c; Received: by mail-vc0-f172.google.com with SMTP id lf12so6118703vcb.3 for ; Mon, 02 Jun 2014 22:03:27 -0700 (PDT) X-Received: by 10.58.100.244 with SMTP id fb20mr5527416veb.39.1401771807877; Mon, 02 Jun 2014 22:03:27 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.220.221.72 with SMTP id ib8csp149147vcb; Mon, 2 Jun 2014 22:03:27 -0700 (PDT) X-Received: by 10.68.242.135 with SMTP id wq7mr46304395pbc.147.1401771807045; Mon, 02 Jun 2014 22:03:27 -0700 (PDT) Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id ek4si18536851pbc.5.2014.06.02.22.03.26 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 02 Jun 2014 22:03:27 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-return-112986-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Received: (qmail 10497 invoked by alias); 3 Jun 2014 05:03:20 -0000 Mailing-List: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org Precedence: list List-Id: List-Unsubscribe: , List-Subscribe: List-Archive: List-Post: , List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 10487 invoked by uid 89); 3 Jun 2014 05:03:19 -0000 X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.7 required=5.0 tests=AWL, BAYES_00, KAM_STOCKGEN, RP_MATCHES_RCVD, SPF_HELO_PASS, SPF_PASS, UNSUBSCRIBE_BODY autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 03 Jun 2014 05:03:18 +0000 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s5353Hex023993 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Tue, 3 Jun 2014 01:03:17 -0400 Received: from redacted.bos.redhat.com ([10.18.17.143]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s5353FWX002991 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=NO) for ; Tue, 3 Jun 2014 01:03:16 -0400 Date: Tue, 3 Jun 2014 01:03:15 -0400 From: Kyle McMartin To: gdb-patches@sourceware.org Subject: [PATCH 2/2] aarch64: implement walking over the stack protector Message-ID: <20140603050314.GC15355@redacted.bos.redhat.com> MIME-Version: 1.0 In-Reply-To: <20140603050011.GA15355@redacted.bos.redhat.com> User-Agent: Mutt/1.5.23 (2014-03-12) X-IsSubscribed: yes X-Original-Sender: kmcmarti@redhat.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 2607:f8b0:400c:c03::22c as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org; dkim=pass header.i=@sourceware.org X-Google-Group-Id: 836684582541 Content-Disposition: inline Stepping into a function which contains the stack protector sequences currently stops inside the prologue, resulting in us claiming to be on the opening bracket or similar, instead of a useful statement inside the function. Fix that by analysing the prologue instruction, and attempt to walk through the sequence of instructions which set up the stack protector canary. gdb/ 2014-06-03 Kyle McMartin * aarch64-tdep.c (aarch64_skip_stack_chk_guard): New. (aarch64_skip_prologue): Skip over stack protector setup if possible. gdb/testsuite/ 2014-06-03 Kyle McMartin * gdb.arch/aarch64-stack_chk_guard.c: New file. * gdb.arch/aarch64-stack_chk_guard.exp: New file. --- gdb/aarch64-tdep.c | 99 +++++++++++++++++++++- gdb/testsuite/gdb.arch/aarch64-stack_chk_guard.c | 28 ++++++ gdb/testsuite/gdb.arch/aarch64-stack_chk_guard.exp | 43 ++++++++++ 3 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 gdb/testsuite/gdb.arch/aarch64-stack_chk_guard.c create mode 100644 gdb/testsuite/gdb.arch/aarch64-stack_chk_guard.exp diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 9550f42..0c900ce 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -852,6 +852,99 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch, return start; } +/* Attempt to skip the stack protector instructions in a function prologue. + If PC points to the first instruction of the sequence, return the + address of the instruction after the stack protector sequence. Otherwise, + return the original PC. + + On AArch64, the stack protector sequence is composed of four instructions: + + adrp x0, __stack_chk_guard + add x0, x0, #:lo12:__stack_chk_guard + ldr x0, [x0] + str x0, [x29, #end-of-stack] + + Which loads the address of __stack_chk_guard, then loads the guard from it, + and stores it at the end of the stack. */ + +static CORE_ADDR +aarch64_skip_stack_chk_guard (CORE_ADDR pc, struct gdbarch *gdbarch) +{ + enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch); + CORE_ADDR addr = pc; + CORE_ADDR loc = pc; + uint32_t insn; + int64_t imm; + int32_t imm32; + unsigned rd, rd2, rn, rt; + int page; + const int insn_size = 4; + struct bound_minimal_symbol stack_chk_guard; + + /* Attempt to find the label formation of __stack_chk_guard. */ + insn = read_memory_unsigned_integer (loc, insn_size, byte_order_for_code); + if (!decode_adrp (loc, insn, &page, &rd, &imm)) + return pc; + + /* Bail if we saw an ADR instruction, not an ADRP. */ + if (!page) + return pc; + + loc += insn_size; + addr &= ~((1 << 12) - 1); + addr += imm; + + insn = read_memory_unsigned_integer (loc, insn_size, byte_order_for_code); + if (!decode_add_sub_imm (loc, insn, &rd2, &rn, &imm32)) + return pc; + + /* Ensure ADD register matches the ADRP instruction. */ + if (rn != rd) + return pc; + + loc += insn_size; + addr += imm32; + + /* See if we calculated the address of the __stack_chk_guard symbol. */ + stack_chk_guard = lookup_minimal_symbol_by_pc (addr); + if (stack_chk_guard.minsym + && strncmp (MSYMBOL_LINKAGE_NAME (stack_chk_guard.minsym), + "__stack_chk_guard", strlen ("__stack_chk_guard")) != 0) + return pc; + + /* Check if the next instruction is a load from the same registers. */ + insn = read_memory_unsigned_integer (loc, insn_size, byte_order_for_code); + if (decode_masked_match (insn, 0xffc00000, 0xf9400000)) + { + rt = insn & 0x1F; + rn = (insn >> 5) & 0x1F; + + if (rn != rd2) + return pc; + } + else + return pc; + + /* Finally, look for a store of the guard to the stack. */ + loc += insn_size; + insn = read_memory_unsigned_integer (loc, insn_size, byte_order_for_code); + if (decode_masked_match (insn, 0xffc00000, 0xf9000000)) + { + unsigned rt2 = insn & 0x1F; + + /* Check we're storing the guard from the previous load instruction. */ + if (rt2 != rt) + return pc; + } + else + return pc; + + /* If we've made it this far, we've walked through the 4 instruction + sequence around __stack_chk_guard, and can skip over it in the function + prologue. */ + return loc + insn_size; +} + /* Implement the "skip_prologue" gdbarch method. */ static CORE_ADDR @@ -871,7 +964,11 @@ aarch64_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) = skip_prologue_using_sal (gdbarch, func_addr); if (post_prologue_pc != 0) - return max (pc, post_prologue_pc); + { + post_prologue_pc = aarch64_skip_stack_chk_guard (post_prologue_pc, + gdbarch); + return max (pc, post_prologue_pc); + } } /* Can't determine prologue from the symbol table, need to examine diff --git a/gdb/testsuite/gdb.arch/aarch64-stack_chk_guard.c b/gdb/testsuite/gdb.arch/aarch64-stack_chk_guard.c new file mode 100644 index 0000000..3cf52d9 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-stack_chk_guard.c @@ -0,0 +1,28 @@ +/* This file is part of GDB, the GNU debugger. + + Copyright 2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +int stack_chk_guard_fn(void) +{ + /* Needs to be large enough to trigger -fstack-protector. */ + char stack[64]; + return 0; /* Post function prologue statement. */ +} + +int main(void) +{ + return stack_chk_guard_fn(); +} diff --git a/gdb/testsuite/gdb.arch/aarch64-stack_chk_guard.exp b/gdb/testsuite/gdb.arch/aarch64-stack_chk_guard.exp new file mode 100644 index 0000000..7f60867 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-stack_chk_guard.exp @@ -0,0 +1,43 @@ +# Copyright 2014 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# This file is part of the gdb testsuite. + +# Test that we single step past the __stack_chk_guard setup in the +# prologue of functions. + +if {![istarget "aarch64*"]} { + verbose "Skipping ${gdb_test_file_name}." + return +} + +standard_testfile +set additional_flags "additional_flags=-fstack-protector" +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug $additional_flags]] != "" } { + unsupported "compiler does not support -fstack-protector" + return +} + +clean_restart "${binfile}" +if ![runto_main] { + untested "could not run to main" + return -1 +} + +gdb_breakpoint "stack_chk_guard_fn" + +# Previously, we'd see a { as we're still in the function prologue. +gdb_continue_to_breakpoint "continue into stack_chk_guard_fn" ".*return 0;.*"