2011-03-31 Thiago Jung Bauermann <bauerman@br.ibm.com>
Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com> Implement support for PowerPC BookE ranged breakpoints. gdb/ * NEWS: Mention support for ranged breakpoints on embedded PowerPC. * breakpoint.h (struct bp_target_info) <length>: New member variable. (struct breakpoint_ops) <breakpoint_hit>: Take struct bp_location instead of struct breakpoint as argument, and also add ASPACE and BP_ADDR arguments. Update all callers. (struct breakpoint_ops) <print_one_detail>: New method. (struct breakpoint) <addr_string_range_end>: New member variable. * breakpoint.c (breakpoint_location_address_match): Add function prototype. (insert_bp_location): Set bl->target_info.length. (breakpoint_here_p): Call breakpoint_location_address_match. (moribund_breakpoint_here_p): Likewise. (regular_breakpoint_inserted_here_p): Likewise. (breakpoint_thread_match): Likewise. (bpstat_stop_status): Likewise. (bpstat_check_location): Move call to breakpoint_ops.breakpoint_hit to the top. (print_one_breakpoint_location): Call breakpoint_ops.print_one_detail if available. (breakpoint_address_match_range): New function. (breakpoint_location_address_match): Likewise. (breakpoint_locations_match): Compare the length field of the locations too. (hw_breakpoint_used_count): Count resources used by all locations in a breakpoint, and use breakpoint_ops.resources_needed if available. (breakpoint_hit_ranged_breakpoint): New function. (resources_needed_ranged_breakpoint): Likewise. (print_it_ranged_breakpoint): Likewise. (print_one_ranged_breakpoint): Likewise. (print_one_detail_ranged_breakpoint): Likewise. (print_mention_ranged_breakpoint): Likewise. (print_recreate_ranged_breakpoint): Likewise. (ranged_breakpoint_ops): New structure. (find_breakpoint_range_end): New function. (break_range_command): Likewise. (delete_breakpoint): Free addr_string_range_end. (update_breakpoint_locations): Add SALS_END argument. Update all callers. Calculate breakpoint length if a non-zero SALS_END is given. Call breakpoint_locations_match instead of breakpoint_address_match. (reset_breakpoint): Find SaL of the end of the range if B is a ranged breakpoint. (_initialize_breakpoint): Register break-range command. * defs.h (print_core_address): Add function prototype. * ppc-linux-nat.c (ppc_linux_ranged_break_num_registers): New function. (ppc_linux_insert_hw_breakpoint): Support ranged breakpoints. (ppc_linux_remove_hw_breakpoint): Likewise. (_initialize_ppc_linux_nat): Initialize to_ranged_break_num_registers. * target.c (update_current_target): Add comment about to_ranged_break_num_registers. (target_ranged_break_num_registers): New function. * target.h (struct target_ops) <to_ranged_break_num_registers>: New method. (target_ranged_break_num_registers): Add function prototype. * ui-out.c (ui_out_field_core_addr): Move address-printing logic to ... * utils.c (print_core_address): ... here. gdb/doc/ * gdb.texinfo (PowerPC Embedded): Document ranged breakpoints.
This commit is contained in:
parent
bbda34159e
commit
f13101077f
|
@ -1,3 +1,68 @@
|
|||
2011-03-31 Thiago Jung Bauermann <bauerman@br.ibm.com>
|
||||
Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com>
|
||||
|
||||
Implement support for PowerPC BookE ranged breakpoints.
|
||||
* NEWS: Mention support for ranged breakpoints on embedded PowerPC.
|
||||
* breakpoint.h (struct bp_target_info) <length>: New member
|
||||
variable.
|
||||
(struct breakpoint_ops) <breakpoint_hit>: Take struct bp_location
|
||||
instead of struct breakpoint as argument, and also add ASPACE
|
||||
and BP_ADDR arguments. Update all callers.
|
||||
(struct breakpoint_ops) <print_one_detail>: New method.
|
||||
(struct breakpoint) <addr_string_range_end>: New member variable.
|
||||
* breakpoint.c (breakpoint_location_address_match): Add function
|
||||
prototype.
|
||||
(insert_bp_location): Set bl->target_info.length.
|
||||
(breakpoint_here_p): Call breakpoint_location_address_match.
|
||||
(moribund_breakpoint_here_p): Likewise.
|
||||
(regular_breakpoint_inserted_here_p): Likewise.
|
||||
(breakpoint_thread_match): Likewise.
|
||||
(bpstat_stop_status): Likewise.
|
||||
(bpstat_check_location): Move call to
|
||||
breakpoint_ops.breakpoint_hit to the top.
|
||||
(print_one_breakpoint_location): Call
|
||||
breakpoint_ops.print_one_detail if available.
|
||||
(breakpoint_address_match_range): New function.
|
||||
(breakpoint_location_address_match): Likewise.
|
||||
(breakpoint_locations_match): Compare the length field of the
|
||||
locations too.
|
||||
(hw_breakpoint_used_count): Count resources used by all locations
|
||||
in a breakpoint, and use breakpoint_ops.resources_needed if
|
||||
available.
|
||||
(breakpoint_hit_ranged_breakpoint): New function.
|
||||
(resources_needed_ranged_breakpoint): Likewise.
|
||||
(print_it_ranged_breakpoint): Likewise.
|
||||
(print_one_ranged_breakpoint): Likewise.
|
||||
(print_one_detail_ranged_breakpoint): Likewise.
|
||||
(print_mention_ranged_breakpoint): Likewise.
|
||||
(print_recreate_ranged_breakpoint): Likewise.
|
||||
(ranged_breakpoint_ops): New structure.
|
||||
(find_breakpoint_range_end): New function.
|
||||
(break_range_command): Likewise.
|
||||
(delete_breakpoint): Free addr_string_range_end.
|
||||
(update_breakpoint_locations): Add SALS_END argument. Update
|
||||
all callers. Calculate breakpoint length if a non-zero SALS_END
|
||||
is given. Call breakpoint_locations_match instead of
|
||||
breakpoint_address_match.
|
||||
(reset_breakpoint): Find SaL of the end of the range if B is a
|
||||
ranged breakpoint.
|
||||
(_initialize_breakpoint): Register break-range command.
|
||||
* defs.h (print_core_address): Add function prototype.
|
||||
* ppc-linux-nat.c (ppc_linux_ranged_break_num_registers): New
|
||||
function.
|
||||
(ppc_linux_insert_hw_breakpoint): Support ranged breakpoints.
|
||||
(ppc_linux_remove_hw_breakpoint): Likewise.
|
||||
(_initialize_ppc_linux_nat): Initialize
|
||||
to_ranged_break_num_registers.
|
||||
* target.c (update_current_target): Add comment about
|
||||
to_ranged_break_num_registers.
|
||||
(target_ranged_break_num_registers): New function.
|
||||
* target.h (struct target_ops) <to_ranged_break_num_registers>:
|
||||
New method.
|
||||
(target_ranged_break_num_registers): Add function prototype.
|
||||
* ui-out.c (ui_out_field_core_addr): Move address-printing logic to ...
|
||||
* utils.c (print_core_address): ... here.
|
||||
|
||||
2011-03-31 Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* breakpoint.c (addr_string_to_sals): Avoid uninitialized
|
||||
|
|
6
gdb/NEWS
6
gdb/NEWS
|
@ -156,6 +156,12 @@
|
|||
libthread_db library with the "set libthread-db-search-path"
|
||||
command. See the user manual for more details on this command.
|
||||
|
||||
* When natively debugging programs on PowerPC BookE processors running
|
||||
a Linux kernel version 2.6.34 or later, GDB supports ranged breakpoints,
|
||||
which stop execution of the inferior whenever it executes an instruction
|
||||
at any address within the specified range. See the "PowerPC Embedded"
|
||||
section in the user manual for more details.
|
||||
|
||||
* New features in the GDB remote stub, GDBserver
|
||||
|
||||
** GDBserver is now supported on PowerPC LynxOS (versions 4.x and 5.x),
|
||||
|
|
|
@ -10925,6 +10925,7 @@ static struct breakpoint_ops catch_exception_breakpoint_ops =
|
|||
NULL, /* resources_needed */
|
||||
print_it_catch_exception,
|
||||
print_one_catch_exception,
|
||||
NULL, /* print_one_detail */
|
||||
print_mention_catch_exception,
|
||||
print_recreate_catch_exception
|
||||
};
|
||||
|
@ -10964,6 +10965,7 @@ static struct breakpoint_ops catch_exception_unhandled_breakpoint_ops = {
|
|||
NULL, /* resources_needed */
|
||||
print_it_catch_exception_unhandled,
|
||||
print_one_catch_exception_unhandled,
|
||||
NULL, /* print_one_detail */
|
||||
print_mention_catch_exception_unhandled,
|
||||
print_recreate_catch_exception_unhandled
|
||||
};
|
||||
|
@ -11001,6 +11003,7 @@ static struct breakpoint_ops catch_assert_breakpoint_ops = {
|
|||
NULL, /* resources_needed */
|
||||
print_it_catch_assert,
|
||||
print_one_catch_assert,
|
||||
NULL, /* print_one_detail */
|
||||
print_mention_catch_assert,
|
||||
print_recreate_catch_assert
|
||||
};
|
||||
|
|
479
gdb/breakpoint.c
479
gdb/breakpoint.c
|
@ -131,6 +131,10 @@ static int breakpoint_address_match (struct address_space *aspace1,
|
|||
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);
|
||||
|
@ -1537,6 +1541,7 @@ insert_bp_location (struct bp_location *bl,
|
|||
memset (&bl->target_info, 0, sizeof (bl->target_info));
|
||||
bl->target_info.placed_address = bl->address;
|
||||
bl->target_info.placed_address_space = bl->pspace->aspace;
|
||||
bl->target_info.length = bl->length;
|
||||
|
||||
if (bl->loc_type == bp_loc_software_breakpoint
|
||||
|| bl->loc_type == bp_loc_hardware_breakpoint)
|
||||
|
@ -2799,11 +2804,10 @@ breakpoint_here_p (struct address_space *aspace, CORE_ADDR pc)
|
|||
&& bl->loc_type != bp_loc_hardware_breakpoint)
|
||||
continue;
|
||||
|
||||
/* ALL_BP_LOCATIONS bp_location has bl->OWNER always non-NULL. */
|
||||
/* ALL_BP_LOCATIONS bp_location has BL->OWNER always non-NULL. */
|
||||
if ((breakpoint_enabled (bl->owner)
|
||||
|| bl->owner->enable_state == bp_permanent)
|
||||
&& breakpoint_address_match (bl->pspace->aspace, bl->address,
|
||||
aspace, pc))
|
||||
&& breakpoint_location_address_match (bl, aspace, pc))
|
||||
{
|
||||
if (overlay_debugging
|
||||
&& section_is_overlay (bl->section)
|
||||
|
@ -2828,8 +2832,7 @@ moribund_breakpoint_here_p (struct address_space *aspace, CORE_ADDR pc)
|
|||
int ix;
|
||||
|
||||
for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix)
|
||||
if (breakpoint_address_match (loc->pspace->aspace, loc->address,
|
||||
aspace, pc))
|
||||
if (breakpoint_location_address_match (loc, aspace, pc))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
@ -2853,8 +2856,7 @@ regular_breakpoint_inserted_here_p (struct address_space *aspace,
|
|||
continue;
|
||||
|
||||
if (bl->inserted
|
||||
&& breakpoint_address_match (bl->pspace->aspace, bl->address,
|
||||
aspace, pc))
|
||||
&& breakpoint_location_address_match (bl, aspace, pc))
|
||||
{
|
||||
if (overlay_debugging
|
||||
&& section_is_overlay (bl->section)
|
||||
|
@ -2971,8 +2973,7 @@ breakpoint_thread_match (struct address_space *aspace, CORE_ADDR pc,
|
|||
&& bl->owner->enable_state != bp_permanent)
|
||||
continue;
|
||||
|
||||
if (!breakpoint_address_match (bl->pspace->aspace, bl->address,
|
||||
aspace, pc))
|
||||
if (!breakpoint_location_address_match (bl, aspace, pc))
|
||||
continue;
|
||||
|
||||
if (bl->owner->thread != -1)
|
||||
|
@ -3860,6 +3861,9 @@ bpstat_check_location (const struct bp_location *bl,
|
|||
/* BL is from existing struct breakpoint. */
|
||||
gdb_assert (b != NULL);
|
||||
|
||||
if (b->ops && b->ops->breakpoint_hit)
|
||||
return b->ops->breakpoint_hit (bl, aspace, bp_addr);
|
||||
|
||||
/* By definition, the inferior does not report stops at
|
||||
tracepoints. */
|
||||
if (is_tracepoint (b))
|
||||
|
@ -3888,7 +3892,7 @@ bpstat_check_location (const struct bp_location *bl,
|
|||
if (is_hardware_watchpoint (b)
|
||||
&& b->watchpoint_triggered == watch_triggered_no)
|
||||
return 0;
|
||||
|
||||
|
||||
if (b->type == bp_hardware_breakpoint)
|
||||
{
|
||||
if (bl->address != bp_addr)
|
||||
|
@ -3899,13 +3903,6 @@ bpstat_check_location (const struct bp_location *bl,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (b->type == bp_catchpoint)
|
||||
{
|
||||
gdb_assert (b->ops != NULL && b->ops->breakpoint_hit != NULL);
|
||||
if (!b->ops->breakpoint_hit (b))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -4265,8 +4262,7 @@ bpstat_stop_status (struct address_space *aspace,
|
|||
|
||||
for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix)
|
||||
{
|
||||
if (breakpoint_address_match (loc->pspace->aspace, loc->address,
|
||||
aspace, bp_addr))
|
||||
if (breakpoint_location_address_match (loc, aspace, bp_addr))
|
||||
{
|
||||
bs = bpstat_alloc (loc, &bs_link);
|
||||
/* For hits of moribund locations, we should just proceed. */
|
||||
|
@ -4952,9 +4948,12 @@ print_one_breakpoint_location (struct breakpoint *b,
|
|||
ui_out_field_int (uiout, "task", b->task);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ui_out_text (uiout, "\n");
|
||||
|
||||
|
||||
if (!part_of_multiple && b->ops && b->ops->print_one_detail)
|
||||
b->ops->print_one_detail (b, uiout);
|
||||
|
||||
if (!part_of_multiple && b->static_trace_marker_id)
|
||||
{
|
||||
gdb_assert (b->type == bp_static_tracepoint);
|
||||
|
@ -5537,6 +5536,39 @@ breakpoint_address_match (struct address_space *aspace1, CORE_ADDR addr1,
|
|||
&& addr1 == addr2);
|
||||
}
|
||||
|
||||
/* Returns true if {ASPACE2,ADDR2} falls within the range determined by
|
||||
{ASPACE1,ADDR1,LEN1}. In most targets, this can only be true if ASPACE1
|
||||
matches ASPACE2. On targets that have global breakpoints, the address
|
||||
space doesn't really matter. */
|
||||
|
||||
static int
|
||||
breakpoint_address_match_range (struct address_space *aspace1, CORE_ADDR addr1,
|
||||
int len1, struct address_space *aspace2,
|
||||
CORE_ADDR addr2)
|
||||
{
|
||||
return ((gdbarch_has_global_breakpoints (target_gdbarch)
|
||||
|| aspace1 == aspace2)
|
||||
&& addr2 >= addr1 && addr2 < addr1 + len1);
|
||||
}
|
||||
|
||||
/* Returns true if {ASPACE,ADDR} matches the breakpoint BL. BL may be
|
||||
a ranged breakpoint. In most targets, a match happens only if ASPACE
|
||||
matches the breakpoint's address space. On targets that have global
|
||||
breakpoints, the address space doesn't really matter. */
|
||||
|
||||
static int
|
||||
breakpoint_location_address_match (struct bp_location *bl,
|
||||
struct address_space *aspace,
|
||||
CORE_ADDR addr)
|
||||
{
|
||||
return (breakpoint_address_match (bl->pspace->aspace, bl->address,
|
||||
aspace, addr)
|
||||
|| (bl->length
|
||||
&& breakpoint_address_match_range (bl->pspace->aspace,
|
||||
bl->address, bl->length,
|
||||
aspace, addr)));
|
||||
}
|
||||
|
||||
/* Assuming LOC1 and LOC2's types' have meaningful target addresses
|
||||
(breakpoint_address_is_meaningful), returns true if LOC1 and LOC2
|
||||
represent the same location. */
|
||||
|
@ -5559,8 +5591,10 @@ breakpoint_locations_match (struct bp_location *loc1,
|
|||
else if (hw_point1)
|
||||
return watchpoint_locations_match (loc1, loc2);
|
||||
else
|
||||
return breakpoint_address_match (loc1->pspace->aspace, loc1->address,
|
||||
loc2->pspace->aspace, loc2->address);
|
||||
/* We compare bp_location.length in order to cover ranged breakpoints. */
|
||||
return (breakpoint_address_match (loc1->pspace->aspace, loc1->address,
|
||||
loc2->pspace->aspace, loc2->address)
|
||||
&& loc1->length == loc2->length);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -6201,9 +6235,10 @@ remove_catch_fork (struct bp_location *bl)
|
|||
catchpoints. */
|
||||
|
||||
static int
|
||||
breakpoint_hit_catch_fork (struct breakpoint *b)
|
||||
breakpoint_hit_catch_fork (const struct bp_location *bl,
|
||||
struct address_space *aspace, CORE_ADDR bp_addr)
|
||||
{
|
||||
return inferior_has_forked (inferior_ptid, &b->forked_inferior_pid);
|
||||
return inferior_has_forked (inferior_ptid, &bl->owner->forked_inferior_pid);
|
||||
}
|
||||
|
||||
/* Implement the "print_it" breakpoint_ops method for fork
|
||||
|
@ -6272,6 +6307,7 @@ static struct breakpoint_ops catch_fork_breakpoint_ops =
|
|||
NULL, /* resources_needed */
|
||||
print_it_catch_fork,
|
||||
print_one_catch_fork,
|
||||
NULL, /* print_one_detail */
|
||||
print_mention_catch_fork,
|
||||
print_recreate_catch_fork
|
||||
};
|
||||
|
@ -6298,9 +6334,10 @@ remove_catch_vfork (struct bp_location *bl)
|
|||
catchpoints. */
|
||||
|
||||
static int
|
||||
breakpoint_hit_catch_vfork (struct breakpoint *b)
|
||||
breakpoint_hit_catch_vfork (const struct bp_location *bl,
|
||||
struct address_space *aspace, CORE_ADDR bp_addr)
|
||||
{
|
||||
return inferior_has_vforked (inferior_ptid, &b->forked_inferior_pid);
|
||||
return inferior_has_vforked (inferior_ptid, &bl->owner->forked_inferior_pid);
|
||||
}
|
||||
|
||||
/* Implement the "print_it" breakpoint_ops method for vfork
|
||||
|
@ -6368,6 +6405,7 @@ static struct breakpoint_ops catch_vfork_breakpoint_ops =
|
|||
NULL, /* resources_needed */
|
||||
print_it_catch_vfork,
|
||||
print_one_catch_vfork,
|
||||
NULL, /* print_one_detail */
|
||||
print_mention_catch_vfork,
|
||||
print_recreate_catch_vfork
|
||||
};
|
||||
|
@ -6457,12 +6495,14 @@ remove_catch_syscall (struct bp_location *bl)
|
|||
catchpoints. */
|
||||
|
||||
static int
|
||||
breakpoint_hit_catch_syscall (struct breakpoint *b)
|
||||
breakpoint_hit_catch_syscall (const struct bp_location *bl,
|
||||
struct address_space *aspace, CORE_ADDR bp_addr)
|
||||
{
|
||||
/* We must check if we are catching specific syscalls in this
|
||||
breakpoint. If we are, then we must guarantee that the called
|
||||
syscall is the same syscall we are catching. */
|
||||
int syscall_number = 0;
|
||||
const struct breakpoint *b = bl->owner;
|
||||
|
||||
if (!inferior_has_called_syscall (inferior_ptid, &syscall_number))
|
||||
return 0;
|
||||
|
@ -6531,7 +6571,7 @@ print_it_catch_syscall (struct breakpoint *b)
|
|||
|
||||
static void
|
||||
print_one_catch_syscall (struct breakpoint *b,
|
||||
struct bp_location **last_loc)
|
||||
struct bp_location **last_loc)
|
||||
{
|
||||
struct value_print_options opts;
|
||||
|
||||
|
@ -6652,6 +6692,7 @@ static struct breakpoint_ops catch_syscall_breakpoint_ops =
|
|||
NULL, /* resources_needed */
|
||||
print_it_catch_syscall,
|
||||
print_one_catch_syscall,
|
||||
NULL, /* print_one_detail */
|
||||
print_mention_catch_syscall,
|
||||
print_recreate_catch_syscall
|
||||
};
|
||||
|
@ -6747,9 +6788,10 @@ remove_catch_exec (struct bp_location *bl)
|
|||
}
|
||||
|
||||
static int
|
||||
breakpoint_hit_catch_exec (struct breakpoint *b)
|
||||
breakpoint_hit_catch_exec (const struct bp_location *bl,
|
||||
struct address_space *aspace, CORE_ADDR bp_addr)
|
||||
{
|
||||
return inferior_has_execd (inferior_ptid, &b->exec_pathname);
|
||||
return inferior_has_execd (inferior_ptid, &bl->owner->exec_pathname);
|
||||
}
|
||||
|
||||
static enum print_stop_action
|
||||
|
@ -6806,6 +6848,7 @@ static struct breakpoint_ops catch_exec_breakpoint_ops =
|
|||
NULL, /* resources_needed */
|
||||
print_it_catch_exec,
|
||||
print_one_catch_exec,
|
||||
NULL, /* print_one_detail */
|
||||
print_mention_catch_exec,
|
||||
print_recreate_catch_exec
|
||||
};
|
||||
|
@ -6829,13 +6872,22 @@ create_syscall_event_catchpoint (int tempflag, VEC(int) *filter,
|
|||
static int
|
||||
hw_breakpoint_used_count (void)
|
||||
{
|
||||
struct breakpoint *b;
|
||||
int i = 0;
|
||||
struct breakpoint *b;
|
||||
struct bp_location *bl;
|
||||
|
||||
ALL_BREAKPOINTS (b)
|
||||
{
|
||||
if (b->type == bp_hardware_breakpoint && breakpoint_enabled (b))
|
||||
i++;
|
||||
for (bl = b->loc; bl; bl = bl->next)
|
||||
{
|
||||
/* Special types of hardware breakpoints may use more than
|
||||
one register. */
|
||||
if (b->ops && b->ops->resources_needed)
|
||||
i += b->ops->resources_needed (bl);
|
||||
else
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
|
@ -8303,6 +8355,309 @@ stopat_command (char *arg, int from_tty)
|
|||
break_command_1 (arg, 0, from_tty);
|
||||
}
|
||||
|
||||
/* Implement the "breakpoint_hit" breakpoint_ops method for
|
||||
ranged breakpoints. */
|
||||
|
||||
static int
|
||||
breakpoint_hit_ranged_breakpoint (const struct bp_location *bl,
|
||||
struct address_space *aspace,
|
||||
CORE_ADDR bp_addr)
|
||||
{
|
||||
return breakpoint_address_match_range (bl->pspace->aspace, bl->address,
|
||||
bl->length, aspace, bp_addr);
|
||||
}
|
||||
|
||||
/* Implement the "resources_needed" breakpoint_ops method for
|
||||
ranged breakpoints. */
|
||||
|
||||
static int
|
||||
resources_needed_ranged_breakpoint (const struct bp_location *bl)
|
||||
{
|
||||
return target_ranged_break_num_registers ();
|
||||
}
|
||||
|
||||
/* Implement the "print_it" breakpoint_ops method for
|
||||
ranged breakpoints. */
|
||||
|
||||
static enum print_stop_action
|
||||
print_it_ranged_breakpoint (struct breakpoint *b)
|
||||
{
|
||||
struct bp_location *bl = b->loc;
|
||||
|
||||
gdb_assert (b->type == bp_hardware_breakpoint);
|
||||
|
||||
/* Ranged breakpoints have only one location. */
|
||||
gdb_assert (bl && bl->next == NULL);
|
||||
|
||||
annotate_breakpoint (b->number);
|
||||
if (b->disposition == disp_del)
|
||||
ui_out_text (uiout, "\nTemporary ranged breakpoint ");
|
||||
else
|
||||
ui_out_text (uiout, "\nRanged breakpoint ");
|
||||
if (ui_out_is_mi_like_p (uiout))
|
||||
{
|
||||
ui_out_field_string (uiout, "reason",
|
||||
async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT));
|
||||
ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition));
|
||||
}
|
||||
ui_out_field_int (uiout, "bkptno", b->number);
|
||||
ui_out_text (uiout, ", ");
|
||||
|
||||
return PRINT_SRC_AND_LOC;
|
||||
}
|
||||
|
||||
/* Implement the "print_one" breakpoint_ops method for
|
||||
ranged breakpoints. */
|
||||
|
||||
static void
|
||||
print_one_ranged_breakpoint (struct breakpoint *b,
|
||||
struct bp_location **last_loc)
|
||||
{
|
||||
struct bp_location *bl = b->loc;
|
||||
struct value_print_options opts;
|
||||
|
||||
/* Ranged breakpoints have only one location. */
|
||||
gdb_assert (bl && bl->next == NULL);
|
||||
|
||||
get_user_print_options (&opts);
|
||||
|
||||
if (opts.addressprint)
|
||||
/* We don't print the address range here, it will be printed later
|
||||
by print_one_detail_ranged_breakpoint. */
|
||||
ui_out_field_skip (uiout, "addr");
|
||||
annotate_field (5);
|
||||
print_breakpoint_location (b, bl);
|
||||
*last_loc = bl;
|
||||
}
|
||||
|
||||
/* Implement the "print_one_detail" breakpoint_ops method for
|
||||
ranged breakpoints. */
|
||||
|
||||
static void
|
||||
print_one_detail_ranged_breakpoint (const struct breakpoint *b,
|
||||
struct ui_out *uiout)
|
||||
{
|
||||
CORE_ADDR address_start, address_end;
|
||||
struct bp_location *bl = b->loc;
|
||||
struct ui_stream *stb = ui_out_stream_new (uiout);
|
||||
struct cleanup *cleanup = make_cleanup_ui_out_stream_delete (stb);
|
||||
|
||||
gdb_assert (bl);
|
||||
|
||||
address_start = bl->address;
|
||||
address_end = address_start + bl->length - 1;
|
||||
|
||||
ui_out_text (uiout, "\taddress range: ");
|
||||
fprintf_unfiltered (stb->stream, "[%s, %s]",
|
||||
print_core_address (bl->gdbarch, address_start),
|
||||
print_core_address (bl->gdbarch, address_end));
|
||||
ui_out_field_stream (uiout, "addr", stb);
|
||||
ui_out_text (uiout, "\n");
|
||||
|
||||
do_cleanups (cleanup);
|
||||
}
|
||||
|
||||
/* Implement the "print_mention" breakpoint_ops method for
|
||||
ranged breakpoints. */
|
||||
|
||||
static void
|
||||
print_mention_ranged_breakpoint (struct breakpoint *b)
|
||||
{
|
||||
struct bp_location *bl = b->loc;
|
||||
|
||||
gdb_assert (bl);
|
||||
gdb_assert (b->type == bp_hardware_breakpoint);
|
||||
|
||||
if (ui_out_is_mi_like_p (uiout))
|
||||
return;
|
||||
|
||||
printf_filtered (_("Hardware assisted ranged breakpoint %d from %s to %s."),
|
||||
b->number, paddress (bl->gdbarch, bl->address),
|
||||
paddress (bl->gdbarch, bl->address + bl->length - 1));
|
||||
}
|
||||
|
||||
/* Implement the "print_recreate" breakpoint_ops method for
|
||||
ranged breakpoints. */
|
||||
|
||||
static void
|
||||
print_recreate_ranged_breakpoint (struct breakpoint *b, struct ui_file *fp)
|
||||
{
|
||||
fprintf_unfiltered (fp, "break-range %s, %s", b->addr_string,
|
||||
b->addr_string_range_end);
|
||||
}
|
||||
|
||||
/* The breakpoint_ops structure to be used in ranged breakpoints. */
|
||||
|
||||
static struct breakpoint_ops ranged_breakpoint_ops =
|
||||
{
|
||||
NULL, /* insert */
|
||||
NULL, /* remove */
|
||||
breakpoint_hit_ranged_breakpoint,
|
||||
resources_needed_ranged_breakpoint,
|
||||
print_it_ranged_breakpoint,
|
||||
print_one_ranged_breakpoint,
|
||||
print_one_detail_ranged_breakpoint,
|
||||
print_mention_ranged_breakpoint,
|
||||
print_recreate_ranged_breakpoint
|
||||
};
|
||||
|
||||
/* Find the address where the end of the breakpoint range should be
|
||||
placed, given the SAL of the end of the range. This is so that if
|
||||
the user provides a line number, the end of the range is set to the
|
||||
last instruction of the given line. */
|
||||
|
||||
static CORE_ADDR
|
||||
find_breakpoint_range_end (struct symtab_and_line sal)
|
||||
{
|
||||
CORE_ADDR end;
|
||||
|
||||
/* If the user provided a PC value, use it. Otherwise,
|
||||
find the address of the end of the given location. */
|
||||
if (sal.explicit_pc)
|
||||
end = sal.pc;
|
||||
else
|
||||
{
|
||||
int ret;
|
||||
CORE_ADDR start;
|
||||
|
||||
ret = find_line_pc_range (sal, &start, &end);
|
||||
if (!ret)
|
||||
error (_("Could not find location of the end of the range."));
|
||||
|
||||
/* find_line_pc_range returns the start of the next line. */
|
||||
end--;
|
||||
}
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
/* Implement the "break-range" CLI command. */
|
||||
|
||||
static void
|
||||
break_range_command (char *arg, int from_tty)
|
||||
{
|
||||
char *arg_start, *addr_string_start, *addr_string_end;
|
||||
struct linespec_result canonical_start, canonical_end;
|
||||
int bp_count, can_use_bp, length;
|
||||
CORE_ADDR end;
|
||||
struct breakpoint *b;
|
||||
struct symtab_and_line sal_start, sal_end;
|
||||
struct symtabs_and_lines sals_start, sals_end;
|
||||
struct cleanup *cleanup_bkpt;
|
||||
|
||||
/* We don't support software ranged breakpoints. */
|
||||
if (target_ranged_break_num_registers () < 0)
|
||||
error (_("This target does not support hardware ranged breakpoints."));
|
||||
|
||||
bp_count = hw_breakpoint_used_count ();
|
||||
bp_count += target_ranged_break_num_registers ();
|
||||
can_use_bp = target_can_use_hardware_watchpoint (bp_hardware_breakpoint,
|
||||
bp_count, 0);
|
||||
if (can_use_bp < 0)
|
||||
error (_("Hardware breakpoints used exceeds limit."));
|
||||
|
||||
if (arg == NULL || arg[0] == '\0')
|
||||
error(_("No address range specified."));
|
||||
|
||||
sals_start.sals = NULL;
|
||||
sals_start.nelts = 0;
|
||||
init_linespec_result (&canonical_start);
|
||||
|
||||
while (*arg == ' ' || *arg == '\t')
|
||||
arg++;
|
||||
|
||||
parse_breakpoint_sals (&arg, &sals_start, &canonical_start, NULL);
|
||||
|
||||
sal_start = sals_start.sals[0];
|
||||
addr_string_start = canonical_start.canonical[0];
|
||||
cleanup_bkpt = make_cleanup (xfree, addr_string_start);
|
||||
xfree (sals_start.sals);
|
||||
xfree (canonical_start.canonical);
|
||||
|
||||
if (arg[0] != ',')
|
||||
error (_("Too few arguments."));
|
||||
else if (sals_start.nelts == 0)
|
||||
error (_("Could not find location of the beginning of the range."));
|
||||
else if (sals_start.nelts != 1)
|
||||
error (_("Cannot create a ranged breakpoint with multiple locations."));
|
||||
|
||||
resolve_sal_pc (&sal_start);
|
||||
|
||||
arg++; /* Skip the comma. */
|
||||
while (*arg == ' ' || *arg == '\t')
|
||||
arg++;
|
||||
|
||||
/* Parse the end location. */
|
||||
|
||||
sals_end.sals = NULL;
|
||||
sals_end.nelts = 0;
|
||||
init_linespec_result (&canonical_end);
|
||||
arg_start = arg;
|
||||
|
||||
/* We call decode_line_n1 directly here instead of using
|
||||
parse_breakpoint_sals because we need to specify the start location's
|
||||
symtab and line as the default symtab and line for the end of the
|
||||
range. This makes it possible to have ranges like "foo.c:27, +14",
|
||||
where +14 means 14 lines from the start location. */
|
||||
sals_end = decode_line_1 (&arg, 1, sal_start.symtab, sal_start.line,
|
||||
&canonical_end, NULL);
|
||||
|
||||
/* canonical_end can be NULL if it was of the form "*0xdeadbeef". */
|
||||
if (canonical_end.canonical == NULL)
|
||||
canonical_end.canonical = xcalloc (1, sizeof (char **));
|
||||
/* Add the string if not present. */
|
||||
if (arg_start != arg && canonical_end.canonical[0] == NULL)
|
||||
canonical_end.canonical[0] = savestring (arg_start, arg - arg_start);
|
||||
|
||||
sal_end = sals_end.sals[0];
|
||||
addr_string_end = canonical_end.canonical[0];
|
||||
make_cleanup (xfree, addr_string_end);
|
||||
xfree (sals_end.sals);
|
||||
xfree (canonical_end.canonical);
|
||||
|
||||
if (sals_end.nelts == 0)
|
||||
error (_("Could not find location of the end of the range."));
|
||||
else if (sals_end.nelts != 1)
|
||||
error (_("Cannot create a ranged breakpoint with multiple locations."));
|
||||
|
||||
resolve_sal_pc (&sal_end);
|
||||
|
||||
end = find_breakpoint_range_end (sal_end);
|
||||
if (sal_start.pc > end)
|
||||
error (_("Invalid address range, end preceeds start."));
|
||||
|
||||
length = end - sal_start.pc + 1;
|
||||
if (length < 0)
|
||||
/* Length overflowed. */
|
||||
error (_("Address range too large."));
|
||||
else if (length == 1)
|
||||
{
|
||||
/* This range is simple enough to be handled by
|
||||
the `hbreak' command. */
|
||||
hbreak_command (addr_string_start, 1);
|
||||
|
||||
do_cleanups (cleanup_bkpt);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now set up the breakpoint. */
|
||||
b = set_raw_breakpoint (get_current_arch (), sal_start,
|
||||
bp_hardware_breakpoint);
|
||||
set_breakpoint_count (breakpoint_count + 1);
|
||||
b->number = breakpoint_count;
|
||||
b->disposition = disp_donttouch;
|
||||
b->addr_string = addr_string_start;
|
||||
b->addr_string_range_end = addr_string_end;
|
||||
b->ops = &ranged_breakpoint_ops;
|
||||
b->loc->length = length;
|
||||
|
||||
discard_cleanups (cleanup_bkpt);
|
||||
|
||||
mention (b);
|
||||
update_global_location_list (1);
|
||||
}
|
||||
|
||||
/* Return non-zero if EXP is verified as constant. Returned zero
|
||||
means EXP is variable. Also the constant detection may fail for
|
||||
some constant expressions and in such case still falsely return
|
||||
|
@ -8455,6 +8810,7 @@ static struct breakpoint_ops watchpoint_breakpoint_ops =
|
|||
resources_needed_watchpoint,
|
||||
NULL, /* print_it */
|
||||
NULL, /* print_one */
|
||||
NULL, /* print_one_detail */
|
||||
NULL, /* print_mention */
|
||||
NULL /* print_recreate */
|
||||
};
|
||||
|
@ -9233,6 +9589,7 @@ static struct breakpoint_ops gnu_v3_exception_catchpoint_ops = {
|
|||
NULL, /* resources_needed */
|
||||
print_exception_catchpoint,
|
||||
print_one_exception_catchpoint,
|
||||
NULL, /* print_one_detail */
|
||||
print_mention_exception_catchpoint,
|
||||
print_recreate_exception_catchpoint
|
||||
};
|
||||
|
@ -10179,6 +10536,7 @@ delete_breakpoint (struct breakpoint *bpt)
|
|||
xfree (bpt->cond_string);
|
||||
xfree (bpt->cond_exp);
|
||||
xfree (bpt->addr_string);
|
||||
xfree (bpt->addr_string_range_end);
|
||||
xfree (bpt->exp);
|
||||
xfree (bpt->exp_string);
|
||||
xfree (bpt->exp_string_reparse);
|
||||
|
@ -10473,14 +10831,21 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
|
|||
return sal;
|
||||
}
|
||||
|
||||
/* Create new breakpoint locations for B (a hardware or software breakpoint)
|
||||
based on SALS and SALS_END. If SALS_END.NELTS is not zero, then B is
|
||||
a ranged breakpoint. */
|
||||
|
||||
void
|
||||
update_breakpoint_locations (struct breakpoint *b,
|
||||
struct symtabs_and_lines sals)
|
||||
struct symtabs_and_lines sals,
|
||||
struct symtabs_and_lines sals_end)
|
||||
{
|
||||
int i;
|
||||
char *s;
|
||||
struct bp_location *existing_locations = b->loc;
|
||||
|
||||
/* Ranged breakpoints have only one start location and one end location. */
|
||||
gdb_assert (sals_end.nelts == 0 || (sals.nelts == 1 && sals_end.nelts == 1));
|
||||
|
||||
/* If there's no new locations, and all existing locations are
|
||||
pending, don't do anything. This optimizes the common case where
|
||||
all locations are in the same shared library, that was unloaded.
|
||||
|
@ -10501,6 +10866,7 @@ update_breakpoint_locations (struct breakpoint *b,
|
|||
old symtab. */
|
||||
if (b->cond_string != NULL)
|
||||
{
|
||||
char *s;
|
||||
struct gdb_exception e;
|
||||
|
||||
s = b->cond_string;
|
||||
|
@ -10527,6 +10893,13 @@ update_breakpoint_locations (struct breakpoint *b,
|
|||
|
||||
if (b->line_number == 0)
|
||||
b->line_number = sals.sals[i].line;
|
||||
|
||||
if (sals_end.nelts)
|
||||
{
|
||||
CORE_ADDR end = find_breakpoint_range_end (sals_end.sals[0]);
|
||||
|
||||
new_loc->length = end - sals.sals[0].pc + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update locations of permanent breakpoints. */
|
||||
|
@ -10552,8 +10925,7 @@ update_breakpoint_locations (struct breakpoint *b,
|
|||
if (have_ambiguous_names)
|
||||
{
|
||||
for (; l; l = l->next)
|
||||
if (breakpoint_address_match (e->pspace->aspace, e->address,
|
||||
l->pspace->aspace, l->address))
|
||||
if (breakpoint_locations_match (e, l))
|
||||
{
|
||||
l->enabled = 0;
|
||||
break;
|
||||
|
@ -10673,8 +11045,9 @@ static void
|
|||
re_set_breakpoint (struct breakpoint *b)
|
||||
{
|
||||
int found;
|
||||
struct symtabs_and_lines sals;
|
||||
struct symtabs_and_lines sals, sals_end;
|
||||
struct symtabs_and_lines expanded = {0};
|
||||
struct symtabs_and_lines expanded_end = {0};
|
||||
struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
|
||||
|
||||
input_radix = b->input_radix;
|
||||
|
@ -10689,7 +11062,17 @@ re_set_breakpoint (struct breakpoint *b)
|
|||
expanded = expand_line_sal_maybe (sals.sals[0]);
|
||||
}
|
||||
|
||||
update_breakpoint_locations (b, expanded);
|
||||
if (b->addr_string_range_end)
|
||||
{
|
||||
sals_end = addr_string_to_sals (b, b->addr_string_range_end, &found);
|
||||
if (found)
|
||||
{
|
||||
make_cleanup (xfree, sals_end.sals);
|
||||
expanded_end = expand_line_sal_maybe (sals_end.sals[0]);
|
||||
}
|
||||
}
|
||||
|
||||
update_breakpoint_locations (b, expanded, expanded_end);
|
||||
do_cleanups (cleanups);
|
||||
}
|
||||
|
||||
|
@ -12733,7 +13116,23 @@ inferior in all-stop mode, gdb behaves as if always-inserted mode is off."),
|
|||
&show_always_inserted_mode,
|
||||
&breakpoint_set_cmdlist,
|
||||
&breakpoint_show_cmdlist);
|
||||
|
||||
|
||||
add_com ("break-range", class_breakpoint, break_range_command, _("\
|
||||
Set a breakpoint for an address range.\n\
|
||||
break-range START-LOCATION, END-LOCATION\n\
|
||||
where START-LOCATION and END-LOCATION can be one of the following:\n\
|
||||
LINENUM, for that line in the current file,\n\
|
||||
FILE:LINENUM, for that line in that file,\n\
|
||||
+OFFSET, for that number of lines after the current line\n\
|
||||
or the start of the range\n\
|
||||
FUNCTION, for the first line in that function,\n\
|
||||
FILE:FUNCTION, to distinguish among like-named static functions.\n\
|
||||
*ADDRESS, for the instruction at that address.\n\
|
||||
\n\
|
||||
The breakpoint will stop execution of the inferior whenever it executes\n\
|
||||
an instruction at any address within the [START-LOCATION, END-LOCATION]\n\
|
||||
range (including START-LOCATION and END-LOCATION)."));
|
||||
|
||||
automatic_hardware_breakpoints = 1;
|
||||
|
||||
observer_attach_about_to_proceed (breakpoint_about_to_proceed);
|
||||
|
|
|
@ -231,6 +231,10 @@ struct bp_target_info
|
|||
is used to determine the type of breakpoint to insert. */
|
||||
CORE_ADDR placed_address;
|
||||
|
||||
/* If this is a ranged breakpoint, then this field contains the
|
||||
length of the range that will be watched for execution. */
|
||||
int length;
|
||||
|
||||
/* If the breakpoint lives in memory and reading that memory would
|
||||
give back the breakpoint, instead of the original contents, then
|
||||
the original contents are cached here. Only SHADOW_LEN bytes of
|
||||
|
@ -339,7 +343,8 @@ struct bp_location
|
|||
CORE_ADDR address;
|
||||
|
||||
/* For hardware watchpoints, the size of the memory region being
|
||||
watched. */
|
||||
watched. For hardware ranged breakpoints, the size of the
|
||||
breakpoint range. */
|
||||
int length;
|
||||
|
||||
/* Type of hardware watchpoint. */
|
||||
|
@ -397,7 +402,8 @@ struct breakpoint_ops
|
|||
|
||||
/* Return non-zero if the debugger should tell the user that this
|
||||
breakpoint was hit. */
|
||||
int (*breakpoint_hit) (struct breakpoint *);
|
||||
int (*breakpoint_hit) (const struct bp_location *, struct address_space *,
|
||||
CORE_ADDR);
|
||||
|
||||
/* Tell how many hardware resources (debug registers) are needed
|
||||
for this breakpoint. If this function is not provided, then
|
||||
|
@ -412,6 +418,20 @@ struct breakpoint_ops
|
|||
breakpoints". */
|
||||
void (*print_one) (struct breakpoint *, struct bp_location **);
|
||||
|
||||
/* Display extra information about this breakpoint, below the normal
|
||||
breakpoint description in "info breakpoints".
|
||||
|
||||
In the example below, the "address range" line was printed
|
||||
by print_one_detail_ranged_breakpoint.
|
||||
|
||||
(gdb) info breakpoints
|
||||
Num Type Disp Enb Address What
|
||||
2 hw breakpoint keep y in main at test-watch.c:70
|
||||
address range: [0x10000458, 0x100004c7]
|
||||
|
||||
*/
|
||||
void (*print_one_detail) (const struct breakpoint *, struct ui_out *);
|
||||
|
||||
/* Display information about this breakpoint after setting it
|
||||
(roughly speaking; this is called from "mention"). */
|
||||
void (*print_mention) (struct breakpoint *);
|
||||
|
@ -502,6 +522,11 @@ struct breakpoint
|
|||
|
||||
/* String we used to set the breakpoint (malloc'd). */
|
||||
char *addr_string;
|
||||
|
||||
/* For a ranged breakpoint, the string we used to find
|
||||
the end of the range (malloc'd). */
|
||||
char *addr_string_range_end;
|
||||
|
||||
/* Architecture we used to set the breakpoint. */
|
||||
struct gdbarch *gdbarch;
|
||||
/* Language we used to set the breakpoint. */
|
||||
|
@ -904,7 +929,8 @@ extern int breakpoint_thread_match (struct address_space *,
|
|||
extern void until_break_command (char *, int, int);
|
||||
|
||||
extern void update_breakpoint_locations (struct breakpoint *b,
|
||||
struct symtabs_and_lines sals);
|
||||
struct symtabs_and_lines sals,
|
||||
struct symtabs_and_lines sals_end);
|
||||
|
||||
extern void breakpoint_re_set (void);
|
||||
|
||||
|
|
|
@ -532,6 +532,12 @@ extern const char *host_address_to_string (const void *addr);
|
|||
This is usually formatted similar to 0x%lx. */
|
||||
extern const char *paddress (struct gdbarch *gdbarch, CORE_ADDR addr);
|
||||
|
||||
/* Return a string representation in hexadecimal notation of ADDRESS,
|
||||
which is suitable for printing. */
|
||||
|
||||
extern const char *print_core_address (struct gdbarch *gdbarch,
|
||||
CORE_ADDR address);
|
||||
|
||||
/* %d for LONGEST */
|
||||
extern char *plongest (LONGEST l);
|
||||
/* %u for ULONGEST */
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2011-03-31 Thiago Jung Bauermann <bauerman@br.ibm.com>
|
||||
Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com>
|
||||
|
||||
Implement support for PowerPC BookE ranged breakpoints.
|
||||
* gdb.texinfo (PowerPC Embedded): Document ranged breakpoints.
|
||||
|
||||
2011-03-28 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* gdb.texinfo (Set Tracepoints): Fix typo.
|
||||
|
@ -9,7 +15,7 @@
|
|||
|
||||
2011-03-18 Phil Muldoon <pmuldoon@redhat.com>
|
||||
|
||||
PR python/12149
|
||||
PR python/12149
|
||||
|
||||
* gdb.texinfo (Basic Python): Update gdb.write and flush text.
|
||||
|
||||
|
|
|
@ -18742,9 +18742,27 @@ region using one of the following commands (@pxref{Expressions}):
|
|||
(@value{GDBP}) watch @{char[@var{length}]@} @var{address}
|
||||
@end smallexample
|
||||
|
||||
@cindex ranged breakpoint
|
||||
PowerPC embedded processors support hardware accelerated
|
||||
@dfn{ranged breakpoints}. A ranged breakpoint stops execution of
|
||||
the inferior whenever it executes an instruction at any address within
|
||||
the range it specifies. To set a ranged breakpoint in @value{GDBN},
|
||||
use the @code{break-range} command.
|
||||
|
||||
@value{GDBN} provides the following PowerPC-specific commands:
|
||||
|
||||
@table @code
|
||||
@kindex break-range
|
||||
@item break-range @var{start-location}, @var{end-location}
|
||||
Set a breakpoint for an address range.
|
||||
@var{start-location} and @var{end-location} can specify a function name,
|
||||
a line number, an offset of lines from the current line or from the start
|
||||
location, or an address of an instruction (see @ref{Specify Location},
|
||||
for a list of all the possible ways to specify a @var{location}.)
|
||||
The breakpoint will stop execution of the inferior whenever it
|
||||
executes an instruction at any address within the specified range,
|
||||
(including @var{start-location} and @var{end-location}.)
|
||||
|
||||
@kindex set powerpc
|
||||
@item set powerpc soft-float
|
||||
@itemx show powerpc soft-float
|
||||
|
|
|
@ -1011,7 +1011,7 @@ elf_gnu_ifunc_resolver_return_stop (struct breakpoint *b)
|
|||
struct value *value;
|
||||
CORE_ADDR resolved_address, resolved_pc;
|
||||
struct symtab_and_line sal;
|
||||
struct symtabs_and_lines sals;
|
||||
struct symtabs_and_lines sals, sals_end;
|
||||
|
||||
gdb_assert (b->type == bp_gnu_ifunc_resolver_return);
|
||||
|
||||
|
@ -1050,9 +1050,10 @@ elf_gnu_ifunc_resolver_return_stop (struct breakpoint *b)
|
|||
sal = find_pc_line (resolved_pc, 0);
|
||||
sals.nelts = 1;
|
||||
sals.sals = &sal;
|
||||
sals_end.nelts = 0;
|
||||
|
||||
b->type = bp_breakpoint;
|
||||
update_breakpoint_locations (b, sals);
|
||||
update_breakpoint_locations (b, sals, sals_end);
|
||||
}
|
||||
|
||||
struct build_id
|
||||
|
|
|
@ -1637,6 +1637,19 @@ booke_remove_point (struct ppc_hw_breakpoint *b, int tid)
|
|||
hw_breaks[i].hw_break = NULL;
|
||||
}
|
||||
|
||||
/* Return the number of registers needed for a ranged breakpoint. */
|
||||
|
||||
static int
|
||||
ppc_linux_ranged_break_num_registers (struct target_ops *target)
|
||||
{
|
||||
return ((have_ptrace_booke_interface ()
|
||||
&& booke_debug_info.features & PPC_DEBUG_FEATURE_INSN_BP_RANGE)?
|
||||
2 : -1);
|
||||
}
|
||||
|
||||
/* Insert the hardware breakpoint described by BP_TGT. Returns 0 for
|
||||
success, 1 if hardware breakpoints are not supported or -1 for failure. */
|
||||
|
||||
static int
|
||||
ppc_linux_insert_hw_breakpoint (struct gdbarch *gdbarch,
|
||||
struct bp_target_info *bp_tgt)
|
||||
|
@ -1650,12 +1663,24 @@ ppc_linux_insert_hw_breakpoint (struct gdbarch *gdbarch,
|
|||
|
||||
p.version = PPC_DEBUG_CURRENT_VERSION;
|
||||
p.trigger_type = PPC_BREAKPOINT_TRIGGER_EXECUTE;
|
||||
p.addr_mode = PPC_BREAKPOINT_MODE_EXACT;
|
||||
p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
|
||||
p.addr = (uint64_t) bp_tgt->placed_address;
|
||||
p.addr2 = 0;
|
||||
p.condition_value = 0;
|
||||
|
||||
if (bp_tgt->length)
|
||||
{
|
||||
p.addr_mode = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
|
||||
|
||||
/* The breakpoint will trigger if the address of the instruction is
|
||||
within the defined range, as follows: p.addr <= address < p.addr2. */
|
||||
p.addr2 = (uint64_t) bp_tgt->placed_address + bp_tgt->length;
|
||||
}
|
||||
else
|
||||
{
|
||||
p.addr_mode = PPC_BREAKPOINT_MODE_EXACT;
|
||||
p.addr2 = 0;
|
||||
}
|
||||
|
||||
ALL_LWPS (lp, ptid)
|
||||
booke_insert_point (&p, TIDGET (ptid));
|
||||
|
||||
|
@ -1675,12 +1700,24 @@ ppc_linux_remove_hw_breakpoint (struct gdbarch *gdbarch,
|
|||
|
||||
p.version = PPC_DEBUG_CURRENT_VERSION;
|
||||
p.trigger_type = PPC_BREAKPOINT_TRIGGER_EXECUTE;
|
||||
p.addr_mode = PPC_BREAKPOINT_MODE_EXACT;
|
||||
p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
|
||||
p.addr = (uint64_t) bp_tgt->placed_address;
|
||||
p.addr2 = 0;
|
||||
p.condition_value = 0;
|
||||
|
||||
if (bp_tgt->length)
|
||||
{
|
||||
p.addr_mode = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
|
||||
|
||||
/* The breakpoint will trigger if the address of the instruction is within
|
||||
the defined range, as follows: p.addr <= address < p.addr2. */
|
||||
p.addr2 = (uint64_t) bp_tgt->placed_address + bp_tgt->length;
|
||||
}
|
||||
else
|
||||
{
|
||||
p.addr_mode = PPC_BREAKPOINT_MODE_EXACT;
|
||||
p.addr2 = 0;
|
||||
}
|
||||
|
||||
ALL_LWPS (lp, ptid)
|
||||
booke_remove_point (&p, TIDGET (ptid));
|
||||
|
||||
|
@ -2392,6 +2429,7 @@ _initialize_ppc_linux_nat (void)
|
|||
t->to_watchpoint_addr_within_range = ppc_linux_watchpoint_addr_within_range;
|
||||
t->to_can_accel_watchpoint_condition
|
||||
= ppc_linux_can_accel_watchpoint_condition;
|
||||
t->to_ranged_break_num_registers = ppc_linux_ranged_break_num_registers;
|
||||
|
||||
t->to_read_description = ppc_linux_read_description;
|
||||
t->to_auxv_parse = ppc_linux_auxv_parse;
|
||||
|
|
16
gdb/target.c
16
gdb/target.c
|
@ -594,6 +594,7 @@ update_current_target (void)
|
|||
INHERIT (to_can_use_hw_breakpoint, t);
|
||||
INHERIT (to_insert_hw_breakpoint, t);
|
||||
INHERIT (to_remove_hw_breakpoint, t);
|
||||
/* Do not inherit to_ranged_break_num_registers. */
|
||||
INHERIT (to_insert_watchpoint, t);
|
||||
INHERIT (to_remove_watchpoint, t);
|
||||
INHERIT (to_stopped_data_address, t);
|
||||
|
@ -3491,6 +3492,21 @@ target_verify_memory (const gdb_byte *data, CORE_ADDR memaddr, ULONGEST size)
|
|||
tcomplain ();
|
||||
}
|
||||
|
||||
/* The documentation for this function is in its prototype declaration
|
||||
in target.h. */
|
||||
|
||||
int
|
||||
target_ranged_break_num_registers (void)
|
||||
{
|
||||
struct target_ops *t;
|
||||
|
||||
for (t = current_target.beneath; t != NULL; t = t->beneath)
|
||||
if (t->to_ranged_break_num_registers != NULL)
|
||||
return t->to_ranged_break_num_registers (t);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
debug_to_prepare_to_store (struct regcache *regcache)
|
||||
{
|
||||
|
|
|
@ -450,6 +450,7 @@ struct target_ops
|
|||
int (*to_insert_breakpoint) (struct gdbarch *, struct bp_target_info *);
|
||||
int (*to_remove_breakpoint) (struct gdbarch *, struct bp_target_info *);
|
||||
int (*to_can_use_hw_breakpoint) (int, int, int);
|
||||
int (*to_ranged_break_num_registers) (struct target_ops *);
|
||||
int (*to_insert_hw_breakpoint) (struct gdbarch *, struct bp_target_info *);
|
||||
int (*to_remove_hw_breakpoint) (struct gdbarch *, struct bp_target_info *);
|
||||
|
||||
|
@ -1354,6 +1355,11 @@ extern char *target_thread_name (struct thread_info *);
|
|||
#define target_remove_hw_breakpoint(gdbarch, bp_tgt) \
|
||||
(*current_target.to_remove_hw_breakpoint) (gdbarch, bp_tgt)
|
||||
|
||||
/* Return number of debug registers needed for a ranged breakpoint,
|
||||
or -1 if ranged breakpoints are not supported. */
|
||||
|
||||
extern int target_ranged_break_num_registers (void);
|
||||
|
||||
/* Return non-zero if target knows the data address which triggered this
|
||||
target_stopped_by_watchpoint, in such case place it to *ADDR_P. Only the
|
||||
INFERIOR_PTID task is being queried. */
|
||||
|
|
19
gdb/ui-out.c
19
gdb/ui-out.c
|
@ -492,23 +492,8 @@ ui_out_field_core_addr (struct ui_out *uiout,
|
|||
struct gdbarch *gdbarch,
|
||||
CORE_ADDR address)
|
||||
{
|
||||
/* Maximum size string returned by hex_string_custom is 50 chars.
|
||||
This buffer must be bigger than that, for safety. */
|
||||
char addstr[64];
|
||||
int addr_bit = gdbarch_addr_bit (gdbarch);
|
||||
|
||||
if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT))
|
||||
address &= ((CORE_ADDR) 1 << addr_bit) - 1;
|
||||
|
||||
/* FIXME: cagney/2002-05-03: Need local_address_string() function
|
||||
that returns the language localized string formatted to a width
|
||||
based on gdbarch_addr_bit. */
|
||||
if (addr_bit <= 32)
|
||||
strcpy (addstr, hex_string_custom (address, 8));
|
||||
else
|
||||
strcpy (addstr, hex_string_custom (address, 16));
|
||||
|
||||
ui_out_field_string (uiout, fldname, addstr);
|
||||
ui_out_field_string (uiout, fldname,
|
||||
print_core_address (gdbarch, address));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
19
gdb/utils.c
19
gdb/utils.c
|
@ -3224,6 +3224,25 @@ paddress (struct gdbarch *gdbarch, CORE_ADDR addr)
|
|||
return hex_string (addr);
|
||||
}
|
||||
|
||||
/* This function is described in "defs.h". */
|
||||
|
||||
const char *
|
||||
print_core_address (struct gdbarch *gdbarch, CORE_ADDR address)
|
||||
{
|
||||
int addr_bit = gdbarch_addr_bit (gdbarch);
|
||||
|
||||
if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT))
|
||||
address &= ((CORE_ADDR) 1 << addr_bit) - 1;
|
||||
|
||||
/* FIXME: cagney/2002-05-03: Need local_address_string() function
|
||||
that returns the language localized string formatted to a width
|
||||
based on gdbarch_addr_bit. */
|
||||
if (addr_bit <= 32)
|
||||
return hex_string_custom (address, 8);
|
||||
else
|
||||
return hex_string_custom (address, 16);
|
||||
}
|
||||
|
||||
static char *
|
||||
decimal2str (char *sign, ULONGEST addr, int width)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue