forked from gbenson/binutils-gdb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbreakpoint.c
16524 lines (13821 loc) · 467 KB
/
breakpoint.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* Everything about breakpoints, for GDB.
Copyright (C) 1986-2015 Free Software Foundation, Inc.
This file is part of GDB.
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 <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "arch-utils.h"
#include <ctype.h>
#include "hashtab.h"
#include "symtab.h"
#include "frame.h"
#include "breakpoint.h"
#include "tracepoint.h"
#include "gdbtypes.h"
#include "expression.h"
#include "gdbcore.h"
#include "gdbcmd.h"
#include "value.h"
#include "command.h"
#include "inferior.h"
#include "infrun.h"
#include "gdbthread.h"
#include "target.h"
#include "language.h"
#include "gdb-demangle.h"
#include "filenames.h"
#include "annotate.h"
#include "symfile.h"
#include "objfiles.h"
#include "source.h"
#include "linespec.h"
#include "completer.h"
#include "gdb.h"
#include "ui-out.h"
#include "cli/cli-script.h"
#include "block.h"
#include "solib.h"
#include "solist.h"
#include "observer.h"
#include "memattr.h"
#include "ada-lang.h"
#include "top.h"
#include "valprint.h"
#include "jit.h"
#include "parser-defs.h"
#include "gdb_regex.h"
#include "probe.h"
#include "cli/cli-utils.h"
#include "continuations.h"
#include "stack.h"
#include "skip.h"
#include "ax-gdb.h"
#include "dummy-frame.h"
#include "interps.h"
#include "format.h"
#include "location.h"
#include "thread-fsm.h"
/* readline include files */
#include "readline/readline.h"
#include "readline/history.h"
/* readline defines this. */
#undef savestring
#include "mi/mi-common.h"
#include "extension.h"
/* Enums for exception-handling support. */
enum exception_event_kind
{
EX_EVENT_THROW,
EX_EVENT_RETHROW,
EX_EVENT_CATCH
};
/* Prototypes for local functions. */
static void enable_delete_command (char *, int);
static void enable_once_command (char *, int);
static void enable_count_command (char *, int);
static void disable_command (char *, int);
static void enable_command (char *, int);
static void map_breakpoint_numbers (char *, void (*) (struct breakpoint *,
void *),
void *);
static void ignore_command (char *, int);
static int breakpoint_re_set_one (void *);
static void breakpoint_re_set_default (struct breakpoint *);
static void
create_sals_from_location_default (const struct event_location *location,
struct linespec_result *canonical,
enum bptype type_wanted);
static void create_breakpoints_sal_default (struct gdbarch *,
struct linespec_result *,
char *, char *, enum bptype,
enum bpdisp, int, int,
int,
const struct breakpoint_ops *,
int, int, int, unsigned);
static void decode_location_default (struct breakpoint *b,
const struct event_location *location,
struct symtabs_and_lines *sals);
static void clear_command (char *, int);
static void catch_command (char *, int);
static int can_use_hardware_watchpoint (struct value *);
static void break_command_1 (char *, int, int);
static void mention (struct breakpoint *);
static struct breakpoint *set_raw_breakpoint_without_location (struct gdbarch *,
enum bptype,
const struct breakpoint_ops *);
static struct bp_location *add_location_to_breakpoint (struct breakpoint *,
const struct symtab_and_line *);
/* This function is used in gdbtk sources and thus can not be made
static. */
struct breakpoint *set_raw_breakpoint (struct gdbarch *gdbarch,
struct symtab_and_line,
enum bptype,
const struct breakpoint_ops *);
static struct breakpoint *
momentary_breakpoint_from_master (struct breakpoint *orig,
enum bptype type,
const struct breakpoint_ops *ops,
int loc_enabled);
static void breakpoint_adjustment_warning (CORE_ADDR, CORE_ADDR, int, int);
static CORE_ADDR adjust_breakpoint_address (struct gdbarch *gdbarch,
CORE_ADDR bpaddr,
enum bptype bptype);
static void describe_other_breakpoints (struct gdbarch *,
struct program_space *, CORE_ADDR,
struct obj_section *, int);
static int watchpoint_locations_match (struct bp_location *loc1,
struct bp_location *loc2);
static int breakpoint_location_address_match (struct bp_location *bl,
struct address_space *aspace,
CORE_ADDR addr);
static void breakpoints_info (char *, int);
static void watchpoints_info (char *, int);
static int breakpoint_1 (char *, int,
int (*) (const struct breakpoint *));
static int breakpoint_cond_eval (void *);
static void cleanup_executing_breakpoints (void *);
static void commands_command (char *, int);
static void condition_command (char *, int);
typedef enum
{
mark_inserted,
mark_uninserted
}
insertion_state_t;
static int remove_breakpoint (struct bp_location *, insertion_state_t);
static int remove_breakpoint_1 (struct bp_location *, insertion_state_t);
static enum print_stop_action print_bp_stop_message (bpstat bs);
static int watchpoint_check (void *);
static void maintenance_info_breakpoints (char *, int);
static int hw_breakpoint_used_count (void);
static int hw_watchpoint_use_count (struct breakpoint *);
static int hw_watchpoint_used_count_others (struct breakpoint *except,
enum bptype type,
int *other_type_used);
static void hbreak_command (char *, int);
static void thbreak_command (char *, int);
static void enable_breakpoint_disp (struct breakpoint *, enum bpdisp,
int count);
static void stop_command (char *arg, int from_tty);
static void stopin_command (char *arg, int from_tty);
static void stopat_command (char *arg, int from_tty);
static void tcatch_command (char *arg, int from_tty);
static void free_bp_location (struct bp_location *loc);
static void incref_bp_location (struct bp_location *loc);
static void decref_bp_location (struct bp_location **loc);
static struct bp_location *allocate_bp_location (struct breakpoint *bpt);
/* update_global_location_list's modes of operation wrt to whether to
insert locations now. */
enum ugll_insert_mode
{
/* Don't insert any breakpoint locations into the inferior, only
remove already-inserted locations that no longer should be
inserted. Functions that delete a breakpoint or breakpoints
should specify this mode, so that deleting a breakpoint doesn't
have the side effect of inserting the locations of other
breakpoints that are marked not-inserted, but should_be_inserted
returns true on them.
This behavior is useful is situations close to tear-down -- e.g.,
after an exec, while the target still has execution, but
breakpoint shadows of the previous executable image should *NOT*
be restored to the new image; or before detaching, where the
target still has execution and wants to delete breakpoints from
GDB's lists, and all breakpoints had already been removed from
the inferior. */
UGLL_DONT_INSERT,
/* May insert breakpoints iff breakpoints_should_be_inserted_now
claims breakpoints should be inserted now. */
UGLL_MAY_INSERT,
/* Insert locations now, irrespective of
breakpoints_should_be_inserted_now. E.g., say all threads are
stopped right now, and the user did "continue". We need to
insert breakpoints _before_ resuming the target, but
UGLL_MAY_INSERT wouldn't insert them, because
breakpoints_should_be_inserted_now returns false at that point,
as no thread is running yet. */
UGLL_INSERT
};
static void update_global_location_list (enum ugll_insert_mode);
static void update_global_location_list_nothrow (enum ugll_insert_mode);
static int is_hardware_watchpoint (const struct breakpoint *bpt);
static void insert_breakpoint_locations (void);
static void tracepoints_info (char *, int);
static void delete_trace_command (char *, int);
static void enable_trace_command (char *, int);
static void disable_trace_command (char *, int);
static void trace_pass_command (char *, int);
static void set_tracepoint_count (int num);
static int is_masked_watchpoint (const struct breakpoint *b);
static struct bp_location **get_first_locp_gte_addr (CORE_ADDR address);
/* Return 1 if B refers to a static tracepoint set by marker ("-m"), zero
otherwise. */
static int strace_marker_p (struct breakpoint *b);
/* The breakpoint_ops structure to be inherited by all breakpoint_ops
that are implemented on top of software or hardware breakpoints
(user breakpoints, internal and momentary breakpoints, etc.). */
static struct breakpoint_ops bkpt_base_breakpoint_ops;
/* Internal breakpoints class type. */
static struct breakpoint_ops internal_breakpoint_ops;
/* Momentary breakpoints class type. */
static struct breakpoint_ops momentary_breakpoint_ops;
/* Momentary breakpoints for bp_longjmp and bp_exception class type. */
static struct breakpoint_ops longjmp_breakpoint_ops;
/* The breakpoint_ops structure to be used in regular user created
breakpoints. */
struct breakpoint_ops bkpt_breakpoint_ops;
/* Breakpoints set on probes. */
static struct breakpoint_ops bkpt_probe_breakpoint_ops;
/* Dynamic printf class type. */
struct breakpoint_ops dprintf_breakpoint_ops;
/* The style in which to perform a dynamic printf. This is a user
option because different output options have different tradeoffs;
if GDB does the printing, there is better error handling if there
is a problem with any of the arguments, but using an inferior
function lets you have special-purpose printers and sending of
output to the same place as compiled-in print functions. */
static const char dprintf_style_gdb[] = "gdb";
static const char dprintf_style_call[] = "call";
static const char dprintf_style_agent[] = "agent";
static const char *const dprintf_style_enums[] = {
dprintf_style_gdb,
dprintf_style_call,
dprintf_style_agent,
NULL
};
static const char *dprintf_style = dprintf_style_gdb;
/* The function to use for dynamic printf if the preferred style is to
call into the inferior. The value is simply a string that is
copied into the command, so it can be anything that GDB can
evaluate to a callable address, not necessarily a function name. */
static char *dprintf_function = "";
/* The channel to use for dynamic printf if the preferred style is to
call into the inferior; if a nonempty string, it will be passed to
the call as the first argument, with the format string as the
second. As with the dprintf function, this can be anything that
GDB knows how to evaluate, so in addition to common choices like
"stderr", this could be an app-specific expression like
"mystreams[curlogger]". */
static char *dprintf_channel = "";
/* True if dprintf commands should continue to operate even if GDB
has disconnected. */
static int disconnected_dprintf = 1;
/* A reference-counted struct command_line. This lets multiple
breakpoints share a single command list. */
struct counted_command_line
{
/* The reference count. */
int refc;
/* The command list. */
struct command_line *commands;
};
struct command_line *
breakpoint_commands (struct breakpoint *b)
{
return b->commands ? b->commands->commands : NULL;
}
/* Flag indicating that a command has proceeded the inferior past the
current breakpoint. */
static int breakpoint_proceeded;
const char *
bpdisp_text (enum bpdisp disp)
{
/* NOTE: the following values are a part of MI protocol and
represent values of 'disp' field returned when inferior stops at
a breakpoint. */
static const char * const bpdisps[] = {"del", "dstp", "dis", "keep"};
return bpdisps[(int) disp];
}
/* Prototypes for exported functions. */
/* If FALSE, gdb will not use hardware support for watchpoints, even
if such is available. */
static int can_use_hw_watchpoints;
static void
show_can_use_hw_watchpoints (struct ui_file *file, int from_tty,
struct cmd_list_element *c,
const char *value)
{
fprintf_filtered (file,
_("Debugger's willingness to use "
"watchpoint hardware is %s.\n"),
value);
}
/* If AUTO_BOOLEAN_FALSE, gdb will not attempt to create pending breakpoints.
If AUTO_BOOLEAN_TRUE, gdb will automatically create pending breakpoints
for unrecognized breakpoint locations.
If AUTO_BOOLEAN_AUTO, gdb will query when breakpoints are unrecognized. */
static enum auto_boolean pending_break_support;
static void
show_pending_break_support (struct ui_file *file, int from_tty,
struct cmd_list_element *c,
const char *value)
{
fprintf_filtered (file,
_("Debugger's behavior regarding "
"pending breakpoints is %s.\n"),
value);
}
/* If 1, gdb will automatically use hardware breakpoints for breakpoints
set with "break" but falling in read-only memory.
If 0, gdb will warn about such breakpoints, but won't automatically
use hardware breakpoints. */
static int automatic_hardware_breakpoints;
static void
show_automatic_hardware_breakpoints (struct ui_file *file, int from_tty,
struct cmd_list_element *c,
const char *value)
{
fprintf_filtered (file,
_("Automatic usage of hardware breakpoints is %s.\n"),
value);
}
/* If on, GDB keeps breakpoints inserted even if the inferior is
stopped, and immediately inserts any new breakpoints as soon as
they're created. If off (default), GDB keeps breakpoints off of
the target as long as possible. That is, it delays inserting
breakpoints until the next resume, and removes them again when the
target fully stops. This is a bit safer in case GDB crashes while
processing user input. */
static int always_inserted_mode = 0;
static void
show_always_inserted_mode (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("Always inserted breakpoint mode is %s.\n"),
value);
}
/* See breakpoint.h. */
int
breakpoints_should_be_inserted_now (void)
{
if (gdbarch_has_global_breakpoints (target_gdbarch ()))
{
/* If breakpoints are global, they should be inserted even if no
thread under gdb's control is running, or even if there are
no threads under GDB's control yet. */
return 1;
}
else if (target_has_execution)
{
struct thread_info *tp;
if (always_inserted_mode)
{
/* The user wants breakpoints inserted even if all threads
are stopped. */
return 1;
}
if (threads_are_executing ())
return 1;
/* Don't remove breakpoints yet if, even though all threads are
stopped, we still have events to process. */
ALL_NON_EXITED_THREADS (tp)
if (tp->resumed
&& tp->suspend.waitstatus_pending_p)
return 1;
}
return 0;
}
static const char condition_evaluation_both[] = "host or target";
/* Modes for breakpoint condition evaluation. */
static const char condition_evaluation_auto[] = "auto";
static const char condition_evaluation_host[] = "host";
static const char condition_evaluation_target[] = "target";
static const char *const condition_evaluation_enums[] = {
condition_evaluation_auto,
condition_evaluation_host,
condition_evaluation_target,
NULL
};
/* Global that holds the current mode for breakpoint condition evaluation. */
static const char *condition_evaluation_mode_1 = condition_evaluation_auto;
/* Global that we use to display information to the user (gets its value from
condition_evaluation_mode_1. */
static const char *condition_evaluation_mode = condition_evaluation_auto;
/* Translate a condition evaluation mode MODE into either "host"
or "target". This is used mostly to translate from "auto" to the
real setting that is being used. It returns the translated
evaluation mode. */
static const char *
translate_condition_evaluation_mode (const char *mode)
{
if (mode == condition_evaluation_auto)
{
if (target_supports_evaluation_of_breakpoint_conditions ())
return condition_evaluation_target;
else
return condition_evaluation_host;
}
else
return mode;
}
/* Discovers what condition_evaluation_auto translates to. */
static const char *
breakpoint_condition_evaluation_mode (void)
{
return translate_condition_evaluation_mode (condition_evaluation_mode);
}
/* Return true if GDB should evaluate breakpoint conditions or false
otherwise. */
static int
gdb_evaluates_breakpoint_condition_p (void)
{
const char *mode = breakpoint_condition_evaluation_mode ();
return (mode == condition_evaluation_host);
}
void _initialize_breakpoint (void);
/* Are we executing breakpoint commands? */
static int executing_breakpoint_commands;
/* Are overlay event breakpoints enabled? */
static int overlay_events_enabled;
/* See description in breakpoint.h. */
int target_exact_watchpoints = 0;
/* Walk the following statement or block through all breakpoints.
ALL_BREAKPOINTS_SAFE does so even if the statement deletes the
current breakpoint. */
#define ALL_BREAKPOINTS(B) for (B = breakpoint_chain; B; B = B->next)
#define ALL_BREAKPOINTS_SAFE(B,TMP) \
for (B = breakpoint_chain; \
B ? (TMP=B->next, 1): 0; \
B = TMP)
/* Similar iterator for the low-level breakpoints. SAFE variant is
not provided so update_global_location_list must not be called
while executing the block of ALL_BP_LOCATIONS. */
#define ALL_BP_LOCATIONS(B,BP_TMP) \
for (BP_TMP = bp_location; \
BP_TMP < bp_location + bp_location_count && (B = *BP_TMP); \
BP_TMP++)
/* Iterates through locations with address ADDRESS for the currently selected
program space. BP_LOCP_TMP points to each object. BP_LOCP_START points
to where the loop should start from.
If BP_LOCP_START is a NULL pointer, the macro automatically seeks the
appropriate location to start with. */
#define ALL_BP_LOCATIONS_AT_ADDR(BP_LOCP_TMP, BP_LOCP_START, ADDRESS) \
for (BP_LOCP_START = BP_LOCP_START == NULL ? get_first_locp_gte_addr (ADDRESS) : BP_LOCP_START, \
BP_LOCP_TMP = BP_LOCP_START; \
BP_LOCP_START \
&& (BP_LOCP_TMP < bp_location + bp_location_count \
&& (*BP_LOCP_TMP)->address == ADDRESS); \
BP_LOCP_TMP++)
/* Iterator for tracepoints only. */
#define ALL_TRACEPOINTS(B) \
for (B = breakpoint_chain; B; B = B->next) \
if (is_tracepoint (B))
/* Chains of all breakpoints defined. */
struct breakpoint *breakpoint_chain;
/* Array is sorted by bp_location_compare - primarily by the ADDRESS. */
static struct bp_location **bp_location;
/* Number of elements of BP_LOCATION. */
static unsigned bp_location_count;
/* Maximum alignment offset between bp_target_info.PLACED_ADDRESS and
ADDRESS for the current elements of BP_LOCATION which get a valid
result from bp_location_has_shadow. You can use it for roughly
limiting the subrange of BP_LOCATION to scan for shadow bytes for
an address you need to read. */
static CORE_ADDR bp_location_placed_address_before_address_max;
/* Maximum offset plus alignment between bp_target_info.PLACED_ADDRESS
+ bp_target_info.SHADOW_LEN and ADDRESS for the current elements of
BP_LOCATION which get a valid result from bp_location_has_shadow.
You can use it for roughly limiting the subrange of BP_LOCATION to
scan for shadow bytes for an address you need to read. */
static CORE_ADDR bp_location_shadow_len_after_address_max;
/* The locations that no longer correspond to any breakpoint, unlinked
from bp_location array, but for which a hit may still be reported
by a target. */
VEC(bp_location_p) *moribund_locations = NULL;
/* Number of last breakpoint made. */
static int breakpoint_count;
/* The value of `breakpoint_count' before the last command that
created breakpoints. If the last (break-like) command created more
than one breakpoint, then the difference between BREAKPOINT_COUNT
and PREV_BREAKPOINT_COUNT is more than one. */
static int prev_breakpoint_count;
/* Number of last tracepoint made. */
static int tracepoint_count;
static struct cmd_list_element *breakpoint_set_cmdlist;
static struct cmd_list_element *breakpoint_show_cmdlist;
struct cmd_list_element *save_cmdlist;
/* See declaration at breakpoint.h. */
struct breakpoint *
breakpoint_find_if (int (*func) (struct breakpoint *b, void *d),
void *user_data)
{
struct breakpoint *b = NULL;
ALL_BREAKPOINTS (b)
{
if (func (b, user_data) != 0)
break;
}
return b;
}
/* Return whether a breakpoint is an active enabled breakpoint. */
static int
breakpoint_enabled (struct breakpoint *b)
{
return (b->enable_state == bp_enabled);
}
/* Set breakpoint count to NUM. */
static void
set_breakpoint_count (int num)
{
prev_breakpoint_count = breakpoint_count;
breakpoint_count = num;
set_internalvar_integer (lookup_internalvar ("bpnum"), num);
}
/* Used by `start_rbreak_breakpoints' below, to record the current
breakpoint count before "rbreak" creates any breakpoint. */
static int rbreak_start_breakpoint_count;
/* Called at the start an "rbreak" command to record the first
breakpoint made. */
void
start_rbreak_breakpoints (void)
{
rbreak_start_breakpoint_count = breakpoint_count;
}
/* Called at the end of an "rbreak" command to record the last
breakpoint made. */
void
end_rbreak_breakpoints (void)
{
prev_breakpoint_count = rbreak_start_breakpoint_count;
}
/* Used in run_command to zero the hit count when a new run starts. */
void
clear_breakpoint_hit_counts (void)
{
struct breakpoint *b;
ALL_BREAKPOINTS (b)
b->hit_count = 0;
}
/* Allocate a new counted_command_line with reference count of 1.
The new structure owns COMMANDS. */
static struct counted_command_line *
alloc_counted_command_line (struct command_line *commands)
{
struct counted_command_line *result = XNEW (struct counted_command_line);
result->refc = 1;
result->commands = commands;
return result;
}
/* Increment reference count. This does nothing if CMD is NULL. */
static void
incref_counted_command_line (struct counted_command_line *cmd)
{
if (cmd)
++cmd->refc;
}
/* Decrement reference count. If the reference count reaches 0,
destroy the counted_command_line. Sets *CMDP to NULL. This does
nothing if *CMDP is NULL. */
static void
decref_counted_command_line (struct counted_command_line **cmdp)
{
if (*cmdp)
{
if (--(*cmdp)->refc == 0)
{
free_command_lines (&(*cmdp)->commands);
xfree (*cmdp);
}
*cmdp = NULL;
}
}
/* A cleanup function that calls decref_counted_command_line. */
static void
do_cleanup_counted_command_line (void *arg)
{
decref_counted_command_line (arg);
}
/* Create a cleanup that calls decref_counted_command_line on the
argument. */
static struct cleanup *
make_cleanup_decref_counted_command_line (struct counted_command_line **cmdp)
{
return make_cleanup (do_cleanup_counted_command_line, cmdp);
}
/* Return the breakpoint with the specified number, or NULL
if the number does not refer to an existing breakpoint. */
struct breakpoint *
get_breakpoint (int num)
{
struct breakpoint *b;
ALL_BREAKPOINTS (b)
if (b->number == num)
return b;
return NULL;
}
/* Mark locations as "conditions have changed" in case the target supports
evaluating conditions on its side. */
static void
mark_breakpoint_modified (struct breakpoint *b)
{
struct bp_location *loc;
/* This is only meaningful if the target is
evaluating conditions and if the user has
opted for condition evaluation on the target's
side. */
if (gdb_evaluates_breakpoint_condition_p ()
|| !target_supports_evaluation_of_breakpoint_conditions ())
return;
if (!is_breakpoint (b))
return;
for (loc = b->loc; loc; loc = loc->next)
loc->condition_changed = condition_modified;
}
/* Mark location as "conditions have changed" in case the target supports
evaluating conditions on its side. */
static void
mark_breakpoint_location_modified (struct bp_location *loc)
{
/* This is only meaningful if the target is
evaluating conditions and if the user has
opted for condition evaluation on the target's
side. */
if (gdb_evaluates_breakpoint_condition_p ()
|| !target_supports_evaluation_of_breakpoint_conditions ())
return;
if (!is_breakpoint (loc->owner))
return;
loc->condition_changed = condition_modified;
}
/* Sets the condition-evaluation mode using the static global
condition_evaluation_mode. */
static void
set_condition_evaluation_mode (char *args, int from_tty,
struct cmd_list_element *c)
{
const char *old_mode, *new_mode;
if ((condition_evaluation_mode_1 == condition_evaluation_target)
&& !target_supports_evaluation_of_breakpoint_conditions ())
{
condition_evaluation_mode_1 = condition_evaluation_mode;
warning (_("Target does not support breakpoint condition evaluation.\n"
"Using host evaluation mode instead."));
return;
}
new_mode = translate_condition_evaluation_mode (condition_evaluation_mode_1);
old_mode = translate_condition_evaluation_mode (condition_evaluation_mode);
/* Flip the switch. Flip it even if OLD_MODE == NEW_MODE as one of the
settings was "auto". */
condition_evaluation_mode = condition_evaluation_mode_1;
/* Only update the mode if the user picked a different one. */
if (new_mode != old_mode)
{
struct bp_location *loc, **loc_tmp;
/* If the user switched to a different evaluation mode, we
need to synch the changes with the target as follows:
"host" -> "target": Send all (valid) conditions to the target.
"target" -> "host": Remove all the conditions from the target.
*/
if (new_mode == condition_evaluation_target)
{
/* Mark everything modified and synch conditions with the
target. */
ALL_BP_LOCATIONS (loc, loc_tmp)
mark_breakpoint_location_modified (loc);
}
else
{
/* Manually mark non-duplicate locations to synch conditions
with the target. We do this to remove all the conditions the
target knows about. */
ALL_BP_LOCATIONS (loc, loc_tmp)
if (is_breakpoint (loc->owner) && loc->inserted)
loc->needs_update = 1;
}
/* Do the update. */
update_global_location_list (UGLL_MAY_INSERT);
}
return;
}
/* Shows the current mode of breakpoint condition evaluation. Explicitly shows
what "auto" is translating to. */
static void
show_condition_evaluation_mode (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
if (condition_evaluation_mode == condition_evaluation_auto)
fprintf_filtered (file,
_("Breakpoint condition evaluation "
"mode is %s (currently %s).\n"),
value,
breakpoint_condition_evaluation_mode ());
else
fprintf_filtered (file, _("Breakpoint condition evaluation mode is %s.\n"),
value);
}
/* A comparison function for bp_location AP and BP that is used by
bsearch. This comparison function only cares about addresses, unlike
the more general bp_location_compare function. */
static int
bp_location_compare_addrs (const void *ap, const void *bp)
{
struct bp_location *a = *(void **) ap;
struct bp_location *b = *(void **) bp;
if (a->address == b->address)
return 0;
else
return ((a->address > b->address) - (a->address < b->address));
}
/* Helper function to skip all bp_locations with addresses
less than ADDRESS. It returns the first bp_location that
is greater than or equal to ADDRESS. If none is found, just
return NULL. */
static struct bp_location **
get_first_locp_gte_addr (CORE_ADDR address)
{
struct bp_location dummy_loc;
struct bp_location *dummy_locp = &dummy_loc;
struct bp_location **locp_found = NULL;
/* Initialize the dummy location's address field. */
memset (&dummy_loc, 0, sizeof (struct bp_location));
dummy_loc.address = address;
/* Find a close match to the first location at ADDRESS. */
locp_found = bsearch (&dummy_locp, bp_location, bp_location_count,
sizeof (struct bp_location **),
bp_location_compare_addrs);
/* Nothing was found, nothing left to do. */
if (locp_found == NULL)
return NULL;
/* We may have found a location that is at ADDRESS but is not the first in the
location's list. Go backwards (if possible) and locate the first one. */
while ((locp_found - 1) >= bp_location
&& (*(locp_found - 1))->address == address)
locp_found--;
return locp_found;
}
void
set_breakpoint_condition (struct breakpoint *b, const char *exp,
int from_tty)
{
xfree (b->cond_string);
b->cond_string = NULL;
if (is_watchpoint (b))
{
struct watchpoint *w = (struct watchpoint *) b;
xfree (w->cond_exp);
w->cond_exp = NULL;
}
else
{
struct bp_location *loc;
for (loc = b->loc; loc; loc = loc->next)
{
xfree (loc->cond);
loc->cond = NULL;
/* No need to free the condition agent expression
bytecode (if we have one). We will handle this
when we go through update_global_location_list. */
}
}
if (*exp == 0)