From patchwork Wed Aug 22 10:11:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xavier Roirand X-Patchwork-Id: 29005 Received: (qmail 60170 invoked by alias); 22 Aug 2018 10:11:32 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk 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 60048 invoked by uid 89); 22 Aug 2018 10:11:31 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_NEUTRAL autolearn=ham version=3.3.2 spammy=PIE, Temporary, HX-Received:sk:l5-v6mr, 52810 X-HELO: mail-wr1-f46.google.com Received: from mail-wr1-f46.google.com (HELO mail-wr1-f46.google.com) (209.85.221.46) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 22 Aug 2018 10:11:28 +0000 Received: by mail-wr1-f46.google.com with SMTP id u12-v6so1140712wrr.4 for ; Wed, 22 Aug 2018 03:11:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=adacore-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=+JlQgiaezqihA+P8fl3Xpr1QC525HXpIVKqo1mi5koQ=; b=N/KIJ5rTxKsLwHK5FUqIiq9IklnCncEgaVoSUqDe7bpSF5EUN9K1KcNXsJJdX8hjAI 682ZVIbAHZY8iP8tLxmiD3iywGvJiCo5bPVpVHjM8ZpoV+mkn1KzIGANVDXz9CqW0z3N zppAIJUOnxdOTE5VkG+G1mfN2PyqaZkm3Cd02QSjpcMzZ1Hc2YJhcg7YVVut4eE+MQLh jU7u831h5GMScoK67Sst9aldHffbShqRIl28D69rFlawixwGRYid4WYejQX88Sn8AEBl cr6HcHtiOIaeynprPU6Fr6+Owr58IbiCiA0V0Yz6T3sxO7ApRBiqRmgKlXasRxmV2a3H Hzrw== Return-Path: Received: from adacore.com ([46.18.100.10]) by smtp.gmail.com with ESMTPSA id l72-v6sm4914315wma.17.2018.08.22.03.11.24 (version=TLS1 cipher=AES128-SHA bits=128/128); Wed, 22 Aug 2018 03:11:25 -0700 (PDT) Received: by adacore.com (sSMTP sendmail emulation); Wed, 22 Aug 2018 12:11:24 +0200 From: Xavier Roirand To: gdb-patches@sourceware.org Cc: brobecker@adacore.com, Xavier Roirand Subject: [RFA 2/5] Darwin: Handle unrelocated dyld. Date: Wed, 22 Aug 2018 12:11:14 +0200 Message-Id: <1534932677-9496-3-git-send-email-roirand@adacore.com> In-Reply-To: <1534932677-9496-1-git-send-email-roirand@adacore.com> References: <1534932677-9496-1-git-send-email-roirand@adacore.com> X-IsSubscribed: yes On Darwin, debugging an helloworld program with GDB does not work and ends with: (gdb) set startup-with-shell off (gdb) start Temporary breakpoint 1 at 0x100000fb4: file /tmp/helloworld.c, line 1. Starting program: /private/tmp/helloworld [New Thread 0x2703 of process 18906] [New Thread 0x2603 of process 18906] [1]+ Stopped ./gdb/gdb /tmp/helloworld When debugging with lldb, instead of having the STOP signal, we can see that a breakpoint is not set to a proper location: Warning: Cannot insert breakpoint -1. Cannot access memory at address 0xf726 Command aborted. The inserted breakpoint is the one used when GDB has to stop the target when a shared library is loaded or unloaded. The notifier address used for adding the breakpoint is wrong thus the above failure. This notifier address is an offset relative to dyld base address, so the value calculation has to be updated to reflect this. This patch fix this. gdb/ChangeLog: * solib-darwin.c (struct darwin_info): Add notifier_set field. (darwin_get_dyld_bfd): New function. (darwin_solib_get_all_image_info_addr_at_init): Update call. (darwin_handle_solib_event): New function. (darwin_solib_create_inferior_hook): Handle unrelocated dyld. (_initialize_darwin_solib): Add solib_event. Change-Id: I7dde5008c9158f17b78dc89bd7f4bd8a12d4a6e1 --- gdb/solib-darwin.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 102 insertions(+), 9 deletions(-) diff --git a/gdb/solib-darwin.c b/gdb/solib-darwin.c index ed8e0c1..aad3c44 100644 --- a/gdb/solib-darwin.c +++ b/gdb/solib-darwin.c @@ -77,6 +77,9 @@ struct darwin_info /* Gdb copy of dyld_all_info_infos. */ struct gdb_dyld_all_image_infos all_image; + + /* True when a breakpoint has been added on dyld notifier. */ + unsigned int notifier_set; }; /* Per-program-space data key. */ @@ -432,20 +435,19 @@ gdb_bfd_mach_o_fat_extract (bfd *abfd, bfd_format format, /* Extract dyld_all_image_addr when the process was just created, assuming the current PC is at the entry of the dynamic linker. */ -static void -darwin_solib_get_all_image_info_addr_at_init (struct darwin_info *info) +static gdb_bfd_ref_ptr +darwin_get_dyld_bfd (void) { char *interp_name; - CORE_ADDR load_addr = 0; /* This method doesn't work with an attached process. */ if (current_inferior ()->attach_flag) - return; + return NULL; /* Find the program interpreter. */ interp_name = find_program_interpreter (); if (!interp_name) - return; + return NULL; /* Create a bfd for the interpreter. */ gdb_bfd_ref_ptr dyld_bfd (gdb_bfd_open (interp_name, gnutarget, -1)); @@ -459,6 +461,18 @@ darwin_solib_get_all_image_info_addr_at_init (struct darwin_info *info) else dyld_bfd.release (); } + return dyld_bfd; +} + +/* Extract dyld_all_image_addr when the process was just created, assuming the + current PC is at the entry of the dynamic linker. */ + +static void +darwin_solib_get_all_image_info_addr_at_init (struct darwin_info *info) +{ + CORE_ADDR load_addr = 0; + gdb_bfd_ref_ptr dyld_bfd (darwin_get_dyld_bfd ()); + if (dyld_bfd == NULL) return; @@ -502,6 +516,37 @@ darwin_solib_read_all_image_info_addr (struct darwin_info *info) info->all_image_addr = extract_unsigned_integer (buf, len, BFD_ENDIAN_BIG); } +/* Callback called on solib event. + Used when a breakpoint has to be added on the entry point, to wait for + dyld initialization. */ + +static void +darwin_handle_solib_event (void) +{ + struct darwin_info *info = get_darwin_info (); + + /* Nothing to do if notifier was already set. */ + if (info->notifier_set) + return; + info->notifier_set = 1; + + /* Remove breakpoint on entry, but not now (as our caller is iterating on + breakpoints). */ + remove_solib_event_breakpoints_at_next_stop (); + + /* Reload dyld infos. */ + darwin_load_image_infos (info); + + if (info->all_image.count == 0) + { + /* Not expected: no dylibs. */ + return; + } + + /* Insert the real solib event on the dyld notifier. */ + create_solib_event_breakpoint (target_gdbarch (), info->all_image.notifier); +} + /* Shared library startup support. See documentation in solib-svr4.c. */ static void @@ -509,6 +554,7 @@ darwin_solib_create_inferior_hook (int from_tty) { struct darwin_info *info = get_darwin_info (); CORE_ADDR load_addr; + CORE_ADDR notifier; info->all_image_addr = 0; @@ -528,10 +574,6 @@ darwin_solib_create_inferior_hook (int from_tty) return; } - /* Add the breakpoint which is hit by dyld when the list of solib is - modified. */ - create_solib_event_breakpoint (target_gdbarch (), info->all_image.notifier); - if (info->all_image.count != 0) { /* Possible relocate the main executable (PIE). */ @@ -558,6 +600,56 @@ darwin_solib_create_inferior_hook (int from_tty) if (vmaddr != load_addr) objfile_rebase (symfile_objfile, load_addr - vmaddr); } + + /* Set solib notifier (to reload list of shared libraries). */ + notifier = info->all_image.notifier; + info->notifier_set = 1; + + if (info->all_image.count == 0) + { + CORE_ADDR start; + + /* Dyld hasn't yet relocated itself, so the notifier address may be + incorrect (as it has to be relocated). + (Apparently dyld doesn't need to relocate itself on x86-64 darwin, + but don't assume that). + Set an event breakpoint at the entry point. */ + start = bfd_get_start_address (exec_bfd); + if (start == 0) + notifier = 0; + else + { + gdb_bfd_ref_ptr dyld_bfd (darwin_get_dyld_bfd ()); + if (dyld_bfd != NULL) + { + CORE_ADDR dyld_bfd_start_address; + CORE_ADDR dyld_relocated_base_address; + CORE_ADDR pc; + + dyld_bfd_start_address = bfd_get_start_address (dyld_bfd.get()); + + /* We find the dynamic linker's base address by examining + the current pc (which should point at the entry point + for the dynamic linker) and subtracting the offset of + the entry point. */ + + pc = regcache_read_pc (get_current_regcache ()); + dyld_relocated_base_address = pc - dyld_bfd_start_address; + + /* We get the proper notifier relocated address by + adding the dyld relocated base address to the current + notifier offset value. */ + + notifier += dyld_relocated_base_address; + info->notifier_set = 0; + } + } + } + + /* Add the breakpoint which is hit by dyld when the list of solib is + modified. */ + if (notifier != 0) + create_solib_event_breakpoint (target_gdbarch (), notifier); } static void @@ -658,4 +750,5 @@ _initialize_darwin_solib (void) darwin_so_ops.in_dynsym_resolve_code = darwin_in_dynsym_resolve_code; darwin_so_ops.lookup_lib_global_symbol = darwin_lookup_lib_symbol; darwin_so_ops.bfd_open = darwin_bfd_open; + darwin_so_ops.handle_event = darwin_handle_solib_event; }