From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from sonic302-21.consmr.mail.ir2.yahoo.com (sonic302-21.consmr.mail.ir2.yahoo.com [87.248.110.84]) by sourceware.org (Postfix) with ESMTPS id C6F73389202F for ; Mon, 25 May 2020 18:57:41 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org C6F73389202F X-YMail-OSG: W61NP3YVM1m1d4FGsjfzM1bOCQIsMmZg3gsafMX2m1qJJebROiji3ZPW7vpB7_B Yi35Rurmrh4bg9KwwwLPBDt.JWJK.gnXx1kL1v7gGB6h4Hb0FeZ8KqK12x4NlvsH2F6ldUH2HXP7 1Ez1xqmIc67t5YXA9qhUYUO4QgodM35S4gr9mJlAMBPvsFWPJBrdsI0fulyySMUn.QuTmPb0ZBIc n_JABxaBFX4hyRq8bRIUorbnpB7DJTs7hBhrk_cEzuwijlQVExccHujABQuzg.HcTmQ9zcLWXXrA FFHieocgvGAYMjk1uT9KUofrbjl27EcU3RSWj.7ErYLgIonePCqrxX50A7MDRbDjWbXKhnI2oqTI HT_TmEqc.vjkbs9NlrCQ4C246RkZZRapf0lB_ZAxnHwxtLHcfZQ3lXak3UCMKQKOJi2hnfCEiBCR ceZZaz8An5ufB2hJQw.YVjs340iHbMpRzpwbZVXRm.0DPMT1ETjMnOdbyUm4zTC4LwEnuijezhMJ Ph2tLmPZxldIZc3UnOKMtvmRia5LX.ROxJYkCptixwN.SNkVjjaIeHOzkcpMk95cDE1LSW8k46YR asGDg59i7LcN6Z4QHp_R3yhE6vqWY3nd.PiZuvuEnrHSZwIXCg4N3gWz2nLKTmWQpSC_ZuzN5CfQ DaI2dkzf.6eCLgh9HpDHz2FEWUpKhoW4e2CsVoG2Nxv3LHujoh_n5OYeMkkE0TWJBuDZL4UXHkzn LJ8CaqclmRgt2fmG2PfiT7Lbx0myOkwqb9OTctoG7wolpoGQPrTbUXkxk.jJNaiLLxTv0vZ0sTya yM9U2EDZut8yFaDrke0vLz2UwvqVI7Dx3q_c3zeW_q34fnUzHEdU9TLDjTvR03A3P0X9wezoqh_F zuINvVFO7plPY8bcqSsZfA98yIThLcrI5EVze1PP6EzM6hVU8sUUlxvUhzXhF.0IsQFTGFgoJDbf LWzuwNCIibZt9_W_2UJxxIukBv.JFRQToE71qfY9c7dFLvoQD6O_.cwcoqWhMTW9QlZPCK1.SB5Q NTLN7h4aBOQWj3ewrvINGVdO4lJWqaWWO3NcqQs2SYnOeZvQg60SjLCbTiARz4DUoqSgjzkhmYxf WLspvcOb.DISGD4cIBWTsp5_M8x_A.AsOVaQU84HwPH75ZwGTTgl6rkzgHw0jKNorRlBJAnCKY1o tP9kgS0ShyglN7E7Le0JKBDyBCNWywdQ47mblzT02W5nIbpww.GNLBMs3QjqwWSvldSJWb7vmcK0 hIw07OTQ8kGMpwONkv3gul3ktPAiDltBbYG3_IwexktW0VK0MutfsnnOIQwvyaElSzcnN8duhsbA wlcJSHfOLw2frenhJbbF9ohNugx6FWBwsTWgAoGtWQRxtwhgAm8nALXsvWaOwWMEqh43gTCtmEtQ b086QgLnuRX8IHtMcxXiNztuj0gYGZ4M- Received: from sonic.gate.mail.ne1.yahoo.com by sonic302.consmr.mail.ir2.yahoo.com with HTTP; Mon, 25 May 2020 18:57:40 +0000 Received: by smtp423.mail.ir2.yahoo.com (VZM Hermes SMTP Server) with ESMTPA ID 8e39fad2073e4e08fe0b9c0b29120b31; Mon, 25 May 2020 18:57:35 +0000 (UTC) From: Hannes Domani To: gdb-patches@sourceware.org Subject: [PATCH 7/7] Reset Windows hardware breakpoints on executable's entry point Date: Mon, 25 May 2020 20:56:59 +0200 Message-Id: <20200525185659.59346-8-ssbssa@yahoo.de> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200525185659.59346-1-ssbssa@yahoo.de> References: <20200525185659.59346-1-ssbssa@yahoo.de> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Antivirus: Avast (VPS 200524-0, 05/24/2020), Outbound message X-Antivirus-Status: Clean X-Spam-Status: No, score=-12.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 25 May 2020 18:57:45 -0000 Fixes these testsuite fails on Windows (actually more, but the others are cascading failures): FAIL: gdb.base/hbreak2.exp: hardware breakpoint insertion (the program exited) FAIL: gdb.base/hbreak2.exp: run until function breakpoint (the program exited) FAIL: gdb.base/hbreak2.exp: run to factorial(6) (the program exited) FAIL: gdb.base/hbreak2.exp: run until hardware function breakpoint, optimized file (the program exited) The problem happens if you only have hardware breakpoints active when (re-)starting the program: (gdb) start Temporary breakpoint 1 at 0x401650: file C:/src/repos/binutils-gdb.git/gdb/tests uite/gdb.base/break.c, line 43. Starting program: C:\gdb\build64\gdb-git\gdb\testsuite\outputs\gdb.base\hbreak2\ hbreak2.exe Temporary breakpoint 1, main (argc=1, argv=0x7e2120, envp=0x7e2900) at C:/src/repos/binutils-gdb.git/gdb/testsuite/gdb.base/break.c:43 43 if (argc == 12345) { /* an unlikely value < 2^16, in case uninited */ /* set breakpoint 6 here */ (gdb) hb factorial Hardware assisted breakpoint 2 at 0x401703: file C:/src/repos/binutils-gdb.git/g db/testsuite/gdb.base/break.c, line 63. (gdb) r The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: C:\gdb\build64\gdb-git\gdb\testsuite\outputs\gdb.base\hbreak2\ hbreak2.exe 720 [Inferior 1 (process 7836) exited normally] But if you stopped just once before reaching the hardware breakpoint, it works fine: (gdb) start Temporary breakpoint 3 at 0x401650: file C:/src/repos/binutils-gdb.git/gdb/tests uite/gdb.base/break.c, line 43. Starting program: C:\gdb\build64\gdb-git\gdb\testsuite\outputs\gdb.base\hbreak2\ hbreak2.exe Temporary breakpoint 3, main (argc=1, argv=0x322120, envp=0x322900) at C:/src/repos/binutils-gdb.git/gdb/testsuite/gdb.base/break.c:43 43 if (argc == 12345) { /* an unlikely value < 2^16, in case uninited */ /* set breakpoint 6 here */ (gdb) c Continuing. Breakpoint 2, factorial (value=6) at C:/src/repos/binutils-gdb.git/gdb/testsuite/gdb.base/break.c:63 63 if (value > 1) { /* set breakpoint 7 here */ I found out that cdb writes this error when trying to do the same: Unable to set breakpoint error The system resets thread contexts after the process breakpoint so hardware breakpoints cannot be set. Go to the executable's entry point and set it then. So all the hardware breakpoints that were set before (or rather, their debug register information) are practically lost when the process entry point is reached. This patch creates an internal breakpoint on the process entry point, which when it is reached, resets all active hardware breakpoints, and continues execution. --- gdb/windows-tdep.c | 130 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/gdb/windows-tdep.c b/gdb/windows-tdep.c index aa0adeba99..90e4794fc5 100644 --- a/gdb/windows-tdep.c +++ b/gdb/windows-tdep.c @@ -37,6 +37,7 @@ #include "coff/internal.h" #include "libcoff.h" #include "solist.h" +#include "observable.h" #define CYGWIN_DLL_NAME "cygwin1.dll" @@ -870,6 +871,99 @@ windows_get_siginfo_type (struct gdbarch *gdbarch) return siginfo_type; } +/* Windows-specific cached data. This is used by GDB for caching + purposes for each inferior. This helps reduce the overhead of + transfering data from a remote target to the local host. */ +struct windows_info +{ + CORE_ADDR entry_point = 0; +}; + +/* Per-inferior data key. */ +static const struct inferior_key windows_inferior_data; + +/* Frees whatever allocated space there is to be freed and sets INF's + Windows cache data pointer to NULL. */ + +static void +invalidate_windows_cache_inf (struct inferior *inf) +{ + windows_inferior_data.clear (inf); +} + +/* Fetch the Windows cache info for INF. This function always returns a + valid INFO pointer. */ + +static struct windows_info * +get_windows_inferior_data (void) +{ + struct windows_info *info; + struct inferior *inf = current_inferior (); + + info = windows_inferior_data.get (inf); + if (info == NULL) + info = windows_inferior_data.emplace (inf); + + return info; +} + +/* Breakpoint on entry point where any active hardware breakpoints will + be reset. */ +static struct breakpoint_ops entry_point_breakpoint_ops; + +/* Reset active hardware breakpoints. */ + +static bool +reset_hardware_breakpoints (struct breakpoint *b) +{ + if (b->type != bp_hardware_breakpoint + && b->type != bp_hardware_watchpoint + && b->type != bp_read_watchpoint + && b->type != bp_access_watchpoint) + return false; + + struct bp_location *loc; + for (loc = b->loc; loc; loc = loc->next) + if (loc->enabled && loc->pspace == current_program_space + && b->ops->remove_location (loc, REMOVE_BREAKPOINT) == 0) + b->ops->insert_location (loc); + + return false; +} + +/* This breakpoint type should never stop, but when reached, reset + the active hardware breakpoints. */ + +static void +startup_breakpoint_check_status (bpstat bs) +{ + /* Never stop. */ + bs->stop = 0; + + iterate_over_breakpoints (reset_hardware_breakpoints); +} + +/* Update the breakpoint location to the current entry point. */ + +static void +startup_breakpoint_re_set (struct breakpoint *b) +{ + struct windows_info *info = get_windows_inferior_data (); + CORE_ADDR entry_point = info->entry_point; + + /* Do nothing if the entry point didn't change. */ + struct bp_location *loc; + for (loc = b->loc; loc; loc = loc->next) + if (loc->pspace == current_program_space && loc->address == entry_point) + return; + + event_location_up location + = new_address_location (entry_point, nullptr, 0); + std::vector sals; + sals = b->ops->decode_location (b, location.get (), current_program_space); + update_breakpoint_locations (b, current_program_space, sals, {}); +} + /* Implement the "solib_create_inferior_hook" target_so_ops method. */ static void @@ -914,6 +1008,30 @@ windows_solib_create_inferior_hook (int from_tty) if (vmaddr != exec_base) objfile_rebase (symfile_objfile, exec_base - vmaddr); } + + /* Create the entry point breakpoint if it doesn't exist already. */ + if (target_has_execution && exec_base != 0) + { + struct windows_info *info = get_windows_inferior_data (); + CORE_ADDR entry_point = exec_base + + pe_data (exec_bfd)->pe_opthdr.AddressOfEntryPoint; + info->entry_point = entry_point; + + breakpoint *startup_breakpoint + = iterate_over_breakpoints ([] (breakpoint *bp) + { + return bp->ops == &entry_point_breakpoint_ops; + }); + if (startup_breakpoint == nullptr) + { + event_location_up location + = new_address_location (entry_point, nullptr, 0); + create_breakpoint (target_gdbarch(), location.get(), nullptr, -1, + nullptr, 0, 1, bp_breakpoint, 0, + AUTO_BOOLEAN_FALSE, &entry_point_breakpoint_ops, + 0, 1, 1, 0); + } + } } static struct target_so_ops windows_so_ops; @@ -1095,6 +1213,18 @@ _initialize_windows_tdep () windows_gdbarch_data_handle = gdbarch_data_register_post_init (init_windows_gdbarch_data); + /* Observers used to invalidate the cache when needed. */ + gdb::observers::inferior_exit.attach (invalidate_windows_cache_inf); + gdb::observers::inferior_appeared.attach (invalidate_windows_cache_inf); + + initialize_breakpoint_ops (); + /* Entry point breakpoint. */ + entry_point_breakpoint_ops = bkpt_breakpoint_ops; + entry_point_breakpoint_ops.check_status + = startup_breakpoint_check_status; + entry_point_breakpoint_ops.re_set + = startup_breakpoint_re_set; + init_w32_command_list (); add_cmd ("thread-information-block", class_info, display_tib, _("Display thread information block."), -- 2.26.2