- Support GNU IFUNCs - indirect functions (BZ 539590).
- Fix bp conditionals [bp_location-accel] regression (Phil Muldoon, BZ 538626). - Fix missed breakpoint location [bp_location-accel] regression (upstream).
This commit is contained in:
parent
6e5cc88fad
commit
9bb4d3d924
@ -2,7 +2,7 @@ http://sourceware.org/gdb/wiki/ProjectArcher
|
|||||||
http://sourceware.org/gdb/wiki/ArcherBranchManagement
|
http://sourceware.org/gdb/wiki/ArcherBranchManagement
|
||||||
|
|
||||||
GIT snapshot:
|
GIT snapshot:
|
||||||
commit 5b73ea6a0f74e63db3b504792fc1d37f548bdf5c
|
commit b125345fb36abbb9bd00128e2093dc636a859da5
|
||||||
|
|
||||||
branch `archer' - the merge of branches:
|
branch `archer' - the merge of branches:
|
||||||
archer-tromey-call-frame-cfa
|
archer-tromey-call-frame-cfa
|
||||||
@ -463,7 +463,7 @@ index 53e7371..d373f8a 100644
|
|||||||
+
|
+
|
||||||
#endif /* BLOCK_H */
|
#endif /* BLOCK_H */
|
||||||
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
|
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
|
||||||
index 811cdfb..b0bf314 100644
|
index 811cdfb..0f35101 100644
|
||||||
--- a/gdb/breakpoint.c
|
--- a/gdb/breakpoint.c
|
||||||
+++ b/gdb/breakpoint.c
|
+++ b/gdb/breakpoint.c
|
||||||
@@ -61,6 +61,7 @@
|
@@ -61,6 +61,7 @@
|
||||||
@ -684,14 +684,14 @@ index 811cdfb..b0bf314 100644
|
|||||||
+
|
+
|
||||||
+ /* Find BC_L which is a leftmost element which may affect BUF content. It is
|
+ /* Find BC_L which is a leftmost element which may affect BUF content. It is
|
||||||
+ safe to report lower value but a failure to report higher one. */
|
+ safe to report lower value but a failure to report higher one. */
|
||||||
+
|
|
||||||
|
- ALL_BP_LOCATIONS (b)
|
||||||
+ bc_l = 0;
|
+ bc_l = 0;
|
||||||
+ bc_r = bp_location_count;
|
+ bc_r = bp_location_count;
|
||||||
+ while (bc_l + 1 < bc_r)
|
+ while (bc_l + 1 < bc_r)
|
||||||
+ {
|
+ {
|
||||||
+ struct bp_location *b;
|
+ struct bp_location *b;
|
||||||
|
+
|
||||||
- ALL_BP_LOCATIONS (b)
|
|
||||||
+ bc = (bc_l + bc_r) / 2;
|
+ bc = (bc_l + bc_r) / 2;
|
||||||
+ b = bp_location[bc];
|
+ b = bp_location[bc];
|
||||||
+
|
+
|
||||||
@ -1553,7 +1553,7 @@ index 811cdfb..b0bf314 100644
|
|||||||
/* If SHOULD_INSERT is false, do not insert any breakpoint locations
|
/* If SHOULD_INSERT is false, do not insert any breakpoint locations
|
||||||
into the inferior, only remove already-inserted locations that no
|
into the inferior, only remove already-inserted locations that no
|
||||||
longer should be inserted. Functions that delete a breakpoint or
|
longer should be inserted. Functions that delete a breakpoint or
|
||||||
@@ -7777,49 +7951,66 @@ static void
|
@@ -7777,49 +7951,78 @@ static void
|
||||||
update_global_location_list (int should_insert)
|
update_global_location_list (int should_insert)
|
||||||
{
|
{
|
||||||
struct breakpoint *b;
|
struct breakpoint *b;
|
||||||
@ -1625,11 +1625,11 @@ index 811cdfb..b0bf314 100644
|
|||||||
{
|
{
|
||||||
- /* Tells if 'loc' is found amoung the new locations. If not, we
|
- /* Tells if 'loc' is found amoung the new locations. If not, we
|
||||||
+ struct bp_location *old_loc = *old_locp;
|
+ struct bp_location *old_loc = *old_locp;
|
||||||
|
+ struct bp_location **loc2p;
|
||||||
+
|
+
|
||||||
+ /* Tells if 'old_loc' is found amoung the new locations. If not, we
|
+ /* Tells if 'old_loc' is found amoung the new locations. If not, we
|
||||||
have to free it. */
|
have to free it. */
|
||||||
- int found_object = 0;
|
int found_object = 0;
|
||||||
+ int found_object;
|
|
||||||
/* Tells if the location should remain inserted in the target. */
|
/* Tells if the location should remain inserted in the target. */
|
||||||
int keep_in_target = 0;
|
int keep_in_target = 0;
|
||||||
int removed = 0;
|
int removed = 0;
|
||||||
@ -1643,13 +1643,24 @@ index 811cdfb..b0bf314 100644
|
|||||||
+ /* Skip LOCP entries which will definitely never be needed. Stop either
|
+ /* Skip LOCP entries which will definitely never be needed. Stop either
|
||||||
+ at or being the one matching OLD_LOC. */
|
+ at or being the one matching OLD_LOC. */
|
||||||
+ while (locp < bp_location + bp_location_count
|
+ while (locp < bp_location + bp_location_count
|
||||||
+ && bp_location_compare (*locp, old_loc) < 0)
|
+ && (*locp)->address < old_loc->address)
|
||||||
+ locp++;
|
+ locp++;
|
||||||
+ found_object = locp < bp_location + bp_location_count && *locp == old_loc;
|
+
|
||||||
|
+ for (loc2p = locp;
|
||||||
|
+ (loc2p < bp_location + bp_location_count
|
||||||
|
+ && (*loc2p)->address == old_loc->address);
|
||||||
|
+ loc2p++)
|
||||||
|
+ {
|
||||||
|
+ if (*loc2p == old_loc)
|
||||||
|
+ {
|
||||||
|
+ found_object = 1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
/* If this location is no longer present, and inserted, look if there's
|
/* If this location is no longer present, and inserted, look if there's
|
||||||
maybe a new location at the same address. If so, mark that one
|
maybe a new location at the same address. If so, mark that one
|
||||||
@@ -7827,11 +8018,11 @@ update_global_location_list (int should_insert)
|
@@ -7827,11 +8030,11 @@ update_global_location_list (int should_insert)
|
||||||
don't have a time window where a breakpoint at certain location is not
|
don't have a time window where a breakpoint at certain location is not
|
||||||
inserted. */
|
inserted. */
|
||||||
|
|
||||||
@ -1663,7 +1674,7 @@ index 811cdfb..b0bf314 100644
|
|||||||
{
|
{
|
||||||
/* The location is still present in the location list, and still
|
/* The location is still present in the location list, and still
|
||||||
should be inserted. Don't do anything. */
|
should be inserted. Don't do anything. */
|
||||||
@@ -7842,37 +8033,46 @@ update_global_location_list (int should_insert)
|
@@ -7842,37 +8045,46 @@ update_global_location_list (int should_insert)
|
||||||
/* The location is either no longer present, or got disabled.
|
/* The location is either no longer present, or got disabled.
|
||||||
See if there's another location at the same address, in which
|
See if there's another location at the same address, in which
|
||||||
case we don't need to remove this one from the target. */
|
case we don't need to remove this one from the target. */
|
||||||
@ -1685,24 +1696,24 @@ index 811cdfb..b0bf314 100644
|
|||||||
+
|
+
|
||||||
+ if (breakpoint_address_is_meaningful (old_loc->owner))
|
+ if (breakpoint_address_is_meaningful (old_loc->owner))
|
||||||
+ {
|
+ {
|
||||||
+ struct bp_location **loc2p;
|
|
||||||
+
|
|
||||||
+ for (loc2p = locp;
|
+ for (loc2p = locp;
|
||||||
+ loc2p < bp_location + bp_location_count
|
+ (loc2p < bp_location + bp_location_count
|
||||||
+ && (*loc2p)->address == old_loc->address;
|
+ && (*loc2p)->address == old_loc->address);
|
||||||
+ loc2p++)
|
+ loc2p++)
|
||||||
+ {
|
+ {
|
||||||
+ struct bp_location *loc2 = *loc2p;
|
+ struct bp_location *loc2 = *loc2p;
|
||||||
+
|
+
|
||||||
+ /* For the sake of should_be_inserted.
|
|
||||||
+ Duplicates check below will fix up this later. */
|
|
||||||
+ loc2->duplicate = 0;
|
|
||||||
+ if (loc2 != old_loc && should_be_inserted (loc2))
|
|
||||||
+ {
|
+ {
|
||||||
+ loc2->inserted = 1;
|
+ /* For the sake of should_be_inserted.
|
||||||
+ loc2->target_info = old_loc->target_info;
|
+ Duplicates check below will fix up this later. */
|
||||||
+ keep_in_target = 1;
|
+ loc2->duplicate = 0;
|
||||||
+ break;
|
+ if (loc2 != old_loc && should_be_inserted (loc2))
|
||||||
|
+ {
|
||||||
|
+ loc2->inserted = 1;
|
||||||
|
+ loc2->target_info = old_loc->target_info;
|
||||||
|
+ keep_in_target = 1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
@ -1728,7 +1739,7 @@ index 811cdfb..b0bf314 100644
|
|||||||
}
|
}
|
||||||
removed = 1;
|
removed = 1;
|
||||||
}
|
}
|
||||||
@@ -7894,19 +8094,59 @@ update_global_location_list (int should_insert)
|
@@ -7894,19 +8106,59 @@ update_global_location_list (int should_insert)
|
||||||
longer need to keep this breakpoint. This is just a
|
longer need to keep this breakpoint. This is just a
|
||||||
heuristic, but if it's wrong, we'll report unexpected SIGTRAP,
|
heuristic, but if it's wrong, we'll report unexpected SIGTRAP,
|
||||||
which is usability issue, but not a correctness problem. */
|
which is usability issue, but not a correctness problem. */
|
||||||
@ -1794,7 +1805,7 @@ index 811cdfb..b0bf314 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (breakpoints_always_inserted_mode () && should_insert
|
if (breakpoints_always_inserted_mode () && should_insert
|
||||||
@@ -8083,6 +8323,7 @@ delete_command (char *arg, int from_tty)
|
@@ -8083,6 +8335,7 @@ delete_command (char *arg, int from_tty)
|
||||||
&& b->type != bp_thread_event
|
&& b->type != bp_thread_event
|
||||||
&& b->type != bp_overlay_event
|
&& b->type != bp_overlay_event
|
||||||
&& b->type != bp_longjmp_master
|
&& b->type != bp_longjmp_master
|
||||||
@ -1802,7 +1813,7 @@ index 811cdfb..b0bf314 100644
|
|||||||
&& b->number >= 0)
|
&& b->number >= 0)
|
||||||
{
|
{
|
||||||
breaks_to_delete = 1;
|
breaks_to_delete = 1;
|
||||||
@@ -8102,6 +8343,7 @@ delete_command (char *arg, int from_tty)
|
@@ -8102,6 +8355,7 @@ delete_command (char *arg, int from_tty)
|
||||||
&& b->type != bp_jit_event
|
&& b->type != bp_jit_event
|
||||||
&& b->type != bp_overlay_event
|
&& b->type != bp_overlay_event
|
||||||
&& b->type != bp_longjmp_master
|
&& b->type != bp_longjmp_master
|
||||||
@ -1810,7 +1821,7 @@ index 811cdfb..b0bf314 100644
|
|||||||
&& b->number >= 0)
|
&& b->number >= 0)
|
||||||
delete_breakpoint (b);
|
delete_breakpoint (b);
|
||||||
}
|
}
|
||||||
@@ -8404,6 +8646,7 @@ breakpoint_re_set_one (void *bint)
|
@@ -8404,6 +8658,7 @@ breakpoint_re_set_one (void *bint)
|
||||||
reset later by breakpoint_re_set. */
|
reset later by breakpoint_re_set. */
|
||||||
case bp_overlay_event:
|
case bp_overlay_event:
|
||||||
case bp_longjmp_master:
|
case bp_longjmp_master:
|
||||||
@ -1818,7 +1829,7 @@ index 811cdfb..b0bf314 100644
|
|||||||
delete_breakpoint (b);
|
delete_breakpoint (b);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -8427,6 +8670,8 @@ breakpoint_re_set_one (void *bint)
|
@@ -8427,6 +8682,8 @@ breakpoint_re_set_one (void *bint)
|
||||||
case bp_longjmp:
|
case bp_longjmp:
|
||||||
case bp_longjmp_resume:
|
case bp_longjmp_resume:
|
||||||
case bp_jit_event:
|
case bp_jit_event:
|
||||||
@ -1827,7 +1838,7 @@ index 811cdfb..b0bf314 100644
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8462,6 +8707,7 @@ breakpoint_re_set (void)
|
@@ -8462,6 +8719,7 @@ breakpoint_re_set (void)
|
||||||
create_longjmp_master_breakpoint ("_longjmp");
|
create_longjmp_master_breakpoint ("_longjmp");
|
||||||
create_longjmp_master_breakpoint ("siglongjmp");
|
create_longjmp_master_breakpoint ("siglongjmp");
|
||||||
create_longjmp_master_breakpoint ("_siglongjmp");
|
create_longjmp_master_breakpoint ("_siglongjmp");
|
||||||
@ -1835,7 +1846,7 @@ index 811cdfb..b0bf314 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the thread number of this breakpoint:
|
/* Reset the thread number of this breakpoint:
|
||||||
@@ -9327,6 +9573,22 @@ all_tracepoints ()
|
@@ -9327,6 +9585,22 @@ all_tracepoints ()
|
||||||
return tp_vec;
|
return tp_vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1858,7 +1869,7 @@ index 811cdfb..b0bf314 100644
|
|||||||
|
|
||||||
/* This help string is used for the break, hbreak, tbreak and thbreak commands.
|
/* This help string is used for the break, hbreak, tbreak and thbreak commands.
|
||||||
It is defined as a macro to prevent duplication.
|
It is defined as a macro to prevent duplication.
|
||||||
@@ -9850,4 +10112,5 @@ inferior in all-stop mode, gdb behaves as if always-inserted mode is off."),
|
@@ -9850,4 +10124,5 @@ inferior in all-stop mode, gdb behaves as if always-inserted mode is off."),
|
||||||
automatic_hardware_breakpoints = 1;
|
automatic_hardware_breakpoints = 1;
|
||||||
|
|
||||||
observer_attach_about_to_proceed (breakpoint_about_to_proceed);
|
observer_attach_about_to_proceed (breakpoint_about_to_proceed);
|
||||||
|
134
gdb-bz538626-bp_location-accel-bp-cond.patch
Normal file
134
gdb-bz538626-bp_location-accel-bp-cond.patch
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
Index: gdb-7.0/gdb/breakpoint.c
|
||||||
|
===================================================================
|
||||||
|
--- gdb-7.0.orig/gdb/breakpoint.c 2009-11-25 10:24:49.000000000 +0100
|
||||||
|
+++ gdb-7.0/gdb/breakpoint.c 2009-11-25 10:28:35.000000000 +0100
|
||||||
|
@@ -337,14 +337,21 @@ static int executing_startup;
|
||||||
|
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++)
|
||||||
|
+/* Similar iterator for the low-level breakpoints. This iterator
|
||||||
|
+ requires a defined BP_LOCATION array and BP_LOCATION_COUNT. */
|
||||||
|
+
|
||||||
|
+#define ALL_BP_LOCATIONS_FROM(B,BP_TMP,BP_LOCATION,BP_LOCATION_COUNT) \
|
||||||
|
+ for (BP_TMP = BP_LOCATION; \
|
||||||
|
+ BP_TMP < BP_LOCATION + BP_LOCATION_COUNT && (B = *BP_TMP); \
|
||||||
|
+ BP_TMP++)
|
||||||
|
+
|
||||||
|
+/* Iterator that calls ALL_BP_LOCATIONS_FROM with the global
|
||||||
|
+ bp_locations and bp_location_count variables. 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) \
|
||||||
|
+ ALL_BP_LOCATIONS_FROM(B,BP_TMP,bp_location, bp_location_count)
|
||||||
|
|
||||||
|
/* Iterator for tracepoints only. */
|
||||||
|
|
||||||
|
@@ -3313,6 +3320,7 @@ bpstat_check_breakpoint_conditions (bpst
|
||||||
|
bpstat
|
||||||
|
bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid)
|
||||||
|
{
|
||||||
|
+ struct cleanup *old_chain;
|
||||||
|
struct breakpoint *b = NULL;
|
||||||
|
struct bp_location *bl, **blp_tmp;
|
||||||
|
struct bp_location *loc;
|
||||||
|
@@ -3322,8 +3330,14 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
|
||||||
|
bpstat bs = root_bs;
|
||||||
|
int ix;
|
||||||
|
int need_remove_insert, update_locations = 0;
|
||||||
|
+ struct bp_location **saved_bp_location;
|
||||||
|
+ int saved_bp_location_count = bp_location_count;
|
||||||
|
|
||||||
|
- ALL_BP_LOCATIONS (bl, blp_tmp)
|
||||||
|
+ saved_bp_location = xmalloc (sizeof (*bp_location) * bp_location_count);
|
||||||
|
+ memcpy (saved_bp_location, bp_location, sizeof (*bp_location) * bp_location_count);
|
||||||
|
+ old_chain = make_cleanup (xfree, saved_bp_location);
|
||||||
|
+
|
||||||
|
+ ALL_BP_LOCATIONS_FROM (bl, blp_tmp, saved_bp_location, saved_bp_location_count)
|
||||||
|
{
|
||||||
|
bpstat bs_prev = bs;
|
||||||
|
|
||||||
|
@@ -3460,6 +3474,7 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
|
||||||
|
insert_breakpoints ();
|
||||||
|
}
|
||||||
|
|
||||||
|
+ do_cleanups (old_chain);
|
||||||
|
return root_bs->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
Index: gdb-7.0/gdb/testsuite/gdb.base/condbreak.exp
|
||||||
|
===================================================================
|
||||||
|
--- gdb-7.0.orig/gdb/testsuite/gdb.base/condbreak.exp 2009-01-03 06:58:03.000000000 +0100
|
||||||
|
+++ gdb-7.0/gdb/testsuite/gdb.base/condbreak.exp 2009-11-25 10:27:50.000000000 +0100
|
||||||
|
@@ -68,6 +68,8 @@ set bp_location1 [gdb_get_line_number "
|
||||||
|
set bp_location6 [gdb_get_line_number "set breakpoint 6 here"]
|
||||||
|
set bp_location8 [gdb_get_line_number "set breakpoint 8 here" $srcfile1]
|
||||||
|
set bp_location9 [gdb_get_line_number "set breakpoint 9 here" $srcfile1]
|
||||||
|
+set bp_location13 [gdb_get_line_number "set breakpoint 13 here" $srcfile1]
|
||||||
|
+set bp_location14 [gdb_get_line_number "set breakpoint 14 here" $srcfile1]
|
||||||
|
set bp_location15 [gdb_get_line_number "set breakpoint 15 here" $srcfile1]
|
||||||
|
set bp_location16 [gdb_get_line_number "set breakpoint 16 here" $srcfile1]
|
||||||
|
|
||||||
|
@@ -110,15 +112,23 @@ gdb_test "break marker2 if (a==43)" \
|
||||||
|
"Breakpoint.*at.* file .*$srcfile1, line.*"
|
||||||
|
|
||||||
|
#
|
||||||
|
+# Check break involving inferior function call.
|
||||||
|
+#
|
||||||
|
+gdb_test "break marker4 if (multi_line_if_conditional(1,1,1)==0)" \
|
||||||
|
+ "Breakpoint.*at.* file .*$srcfile1, line.*"
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
# check to see what breakpoints are set
|
||||||
|
#
|
||||||
|
|
||||||
|
if {$hp_aCC_compiler} {
|
||||||
|
set marker1_proto "\\(void\\)"
|
||||||
|
set marker2_proto "\\(int\\)"
|
||||||
|
+ set marker4_proto "\\(long\\)"
|
||||||
|
} else {
|
||||||
|
set marker1_proto ""
|
||||||
|
set marker2_proto ""
|
||||||
|
+ set marker4_proto ""
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_test "info break" \
|
||||||
|
@@ -129,7 +139,9 @@ gdb_test "info break" \
|
||||||
|
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$bp_location1.*
|
||||||
|
\[\t \]+stop only if \\(1==1\\).*
|
||||||
|
\[0-9\]+\[\t \]+breakpoint keep y.* in marker2$marker2_proto at .*$srcfile1:($bp_location8|$bp_location9).*
|
||||||
|
-\[\t \]+stop only if \\(a==43\\).*" \
|
||||||
|
+\[\t \]+stop only if \\(a==43\\).*
|
||||||
|
+\[0-9\]+\[\t \]+breakpoint keep y.* in marker4$marker4_proto at .*$srcfile1:($bp_location13|$bp_location14).*
|
||||||
|
+\[\t \]+stop only if \\(multi_line_if_conditional\\(1,1,1\\)==0\\).*" \
|
||||||
|
"breakpoint info"
|
||||||
|
|
||||||
|
|
||||||
|
@@ -220,3 +232,19 @@ gdb_expect {
|
||||||
|
fail "(timeout) run until breakpoint at marker2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+send_gdb "continue\n"
|
||||||
|
+gdb_expect {
|
||||||
|
+ -re "Continuing\\..*Breakpoint \[0-9\]+, marker4 \\(d=177601976\\) at .*$srcfile1:($bp_location13|$bp_location14).*($bp_location13|$bp_location14)\[\t \]+.*" {
|
||||||
|
+ pass "run until breakpoint at marker4"
|
||||||
|
+ }
|
||||||
|
+ -re "Continuing\\..*Breakpoint \[0-9\]+, $hex in marker4 \\(d=177601976\\) at .*$srcfile1:($bp_location13|$bp_location14).*($bp_location13|$bp_location14)\[\t \]+.*" {
|
||||||
|
+ xfail "run until breakpoint at marker4"
|
||||||
|
+ }
|
||||||
|
+ -re "$gdb_prompt $" {
|
||||||
|
+ fail "run until breakpoint at marker4"
|
||||||
|
+ }
|
||||||
|
+ timeout {
|
||||||
|
+ fail "(timeout) run until breakpoint at marker4"
|
||||||
|
+ }
|
||||||
|
+}
|
511
gdb-bz539590-gnu-ifunc.patch
Normal file
511
gdb-bz539590-gnu-ifunc.patch
Normal file
@ -0,0 +1,511 @@
|
|||||||
|
gdb/
|
||||||
|
2009-11-24 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||||
|
|
||||||
|
Transparent GNU-IFUNCs support.
|
||||||
|
* elfread.c (record_minimal_symbol): Apply also for mst_text_gnu_ifunc.
|
||||||
|
(elf_symtab_read): Set also mst_text_gnu_ifunc.
|
||||||
|
* gdbtypes.c (init_type): Support TYPE_FLAG_GNU_IFUNC.
|
||||||
|
(gdbtypes_post_init): Initialize builtin_func_func_ptr.
|
||||||
|
(objfile_type): Initialize nodebug_text_gnu_ifunc_symbol.
|
||||||
|
* gdbtypes.h (enum type_flag_value <TYPE_FLAG_GNU_IFUNC>)
|
||||||
|
(TYPE_GNU_IFUNC, struct main_type <flag_gnu_ifunc>)
|
||||||
|
(struct builtin_type <builtin_func_func_ptr>)
|
||||||
|
(struct objfile_type <nodebug_text_gnu_ifunc_symbol>): New.
|
||||||
|
* infcall.c (find_function_addr <TYPE_GNU_IFUNC (ftype)>): New.
|
||||||
|
* minsyms.c (lookup_minimal_symbol_text, prim_record_minimal_symbol)
|
||||||
|
(find_solib_trampoline_target): Support also mst_text_gnu_ifunc.
|
||||||
|
(in_gnu_ifunc_stub): New.
|
||||||
|
* parse.c (write_exp_msymbol <mst_text_gnu_ifunc>): New.
|
||||||
|
* solib-svr4.c (svr4_in_dynsym_resolve_code): Call also
|
||||||
|
in_gnu_ifunc_stub.
|
||||||
|
* symmisc.c (dump_msymbols <mst_text_gnu_ifunc>): New.
|
||||||
|
* symtab.c (search_symbols): Support also mst_text_gnu_ifunc.
|
||||||
|
* symtab.h (enum minimal_symbol_type <mst_text_gnu_ifunc>)
|
||||||
|
(in_gnu_ifunc_stub): New.
|
||||||
|
* linespec.c: Include infcall.h.
|
||||||
|
(minsym_found <MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc>): New.
|
||||||
|
|
||||||
|
gdb/testsuite/
|
||||||
|
2009-11-24 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||||
|
|
||||||
|
Transparent GNU-IFUNCs support.
|
||||||
|
* gdb.base/gnu-ifunc-lib.c, gdb.base/gnu-ifunc.c,
|
||||||
|
gdb.base/gnu-ifunc.exp: New.
|
||||||
|
|
||||||
|
Index: gdb-7.0/gdb/elfread.c
|
||||||
|
===================================================================
|
||||||
|
--- gdb-7.0.orig/gdb/elfread.c 2009-11-25 10:24:45.000000000 +0100
|
||||||
|
+++ gdb-7.0/gdb/elfread.c 2009-11-25 10:25:50.000000000 +0100
|
||||||
|
@@ -168,7 +168,8 @@ record_minimal_symbol (char *name, CORE_
|
||||||
|
{
|
||||||
|
struct gdbarch *gdbarch = get_objfile_arch (objfile);
|
||||||
|
|
||||||
|
- if (ms_type == mst_text || ms_type == mst_file_text)
|
||||||
|
+ if (ms_type == mst_text || ms_type == mst_file_text
|
||||||
|
+ || ms_type == mst_text_gnu_ifunc)
|
||||||
|
address = gdbarch_smash_text_address (gdbarch, address);
|
||||||
|
|
||||||
|
return prim_record_minimal_symbol_and_info
|
||||||
|
@@ -373,7 +374,10 @@ elf_symtab_read (struct objfile *objfile
|
||||||
|
{
|
||||||
|
if (sym->flags & (BSF_GLOBAL | BSF_WEAK))
|
||||||
|
{
|
||||||
|
- ms_type = mst_text;
|
||||||
|
+ if (sym->flags & BSF_GNU_INDIRECT_FUNCTION)
|
||||||
|
+ ms_type = mst_text_gnu_ifunc;
|
||||||
|
+ else
|
||||||
|
+ ms_type = mst_text;
|
||||||
|
}
|
||||||
|
else if ((sym->name[0] == '.' && sym->name[1] == 'L')
|
||||||
|
|| ((sym->flags & BSF_LOCAL)
|
||||||
|
Index: gdb-7.0/gdb/gdbtypes.c
|
||||||
|
===================================================================
|
||||||
|
--- gdb-7.0.orig/gdb/gdbtypes.c 2009-11-25 10:24:47.000000000 +0100
|
||||||
|
+++ gdb-7.0/gdb/gdbtypes.c 2009-11-25 10:24:56.000000000 +0100
|
||||||
|
@@ -1904,6 +1904,8 @@ init_type (enum type_code code, int leng
|
||||||
|
TYPE_NOTTEXT (type) = 1;
|
||||||
|
if (flags & TYPE_FLAG_FIXED_INSTANCE)
|
||||||
|
TYPE_FIXED_INSTANCE (type) = 1;
|
||||||
|
+ if (flags & TYPE_FLAG_GNU_IFUNC)
|
||||||
|
+ TYPE_GNU_IFUNC (type) = 1;
|
||||||
|
|
||||||
|
if (name)
|
||||||
|
TYPE_NAME (type) = obsavestring (name, strlen (name),
|
||||||
|
@@ -3762,6 +3764,8 @@ gdbtypes_post_init (struct gdbarch *gdba
|
||||||
|
= lookup_pointer_type (builtin_type->builtin_void);
|
||||||
|
builtin_type->builtin_func_ptr
|
||||||
|
= lookup_pointer_type (lookup_function_type (builtin_type->builtin_void));
|
||||||
|
+ builtin_type->builtin_func_func_ptr
|
||||||
|
+ = lookup_pointer_type (lookup_function_type (builtin_type->builtin_func_ptr));
|
||||||
|
|
||||||
|
/* This type represents a GDB internal function. */
|
||||||
|
builtin_type->internal_fn
|
||||||
|
@@ -3878,6 +3882,11 @@ objfile_type (struct objfile *objfile)
|
||||||
|
"<text variable, no debug info>", objfile);
|
||||||
|
TYPE_TARGET_TYPE (objfile_type->nodebug_text_symbol)
|
||||||
|
= objfile_type->builtin_int;
|
||||||
|
+ objfile_type->nodebug_text_gnu_ifunc_symbol
|
||||||
|
+ = init_type (TYPE_CODE_FUNC, 1, TYPE_FLAG_GNU_IFUNC,
|
||||||
|
+ "<text gnu-ifunc variable, no debug info>", objfile);
|
||||||
|
+ TYPE_TARGET_TYPE (objfile_type->nodebug_text_gnu_ifunc_symbol)
|
||||||
|
+ = objfile_type->nodebug_text_symbol;
|
||||||
|
objfile_type->nodebug_data_symbol
|
||||||
|
= init_type (TYPE_CODE_INT,
|
||||||
|
gdbarch_int_bit (gdbarch) / HOST_CHAR_BIT, 0,
|
||||||
|
Index: gdb-7.0/gdb/gdbtypes.h
|
||||||
|
===================================================================
|
||||||
|
--- gdb-7.0.orig/gdb/gdbtypes.h 2009-11-25 10:24:48.000000000 +0100
|
||||||
|
+++ gdb-7.0/gdb/gdbtypes.h 2009-11-25 10:25:17.000000000 +0100
|
||||||
|
@@ -187,6 +187,7 @@ enum type_flag_value
|
||||||
|
TYPE_FLAG_FIXED_INSTANCE = (1 << 15),
|
||||||
|
TYPE_FLAG_STUB_SUPPORTED = (1 << 16),
|
||||||
|
TYPE_FLAG_NOTTEXT = (1 << 17),
|
||||||
|
+ TYPE_FLAG_GNU_IFUNC = (1 << 18),
|
||||||
|
|
||||||
|
/* Used for error-checking. */
|
||||||
|
TYPE_FLAG_MIN = TYPE_FLAG_UNSIGNED
|
||||||
|
@@ -292,6 +293,12 @@ enum type_instance_flag_value
|
||||||
|
|
||||||
|
#define TYPE_NOTTEXT(t) (TYPE_MAIN_TYPE (t)->flag_nottext)
|
||||||
|
|
||||||
|
+/* Currently used only for TYPE_CODE_FUNC where specifies the real function
|
||||||
|
+ address is returned by this function call. TYPE_TARGET_TYPE determines the
|
||||||
|
+ final returned function type to be presented to user. */
|
||||||
|
+
|
||||||
|
+#define TYPE_GNU_IFUNC(t) (TYPE_MAIN_TYPE (t)->flag_gnu_ifunc)
|
||||||
|
+
|
||||||
|
/* Type owner. If TYPE_OBJFILE_OWNED is true, the type is owned by
|
||||||
|
the objfile retrieved as TYPE_OBJFILE. Otherweise, the type is
|
||||||
|
owned by an architecture; TYPE_OBJFILE is NULL in this case. */
|
||||||
|
@@ -427,6 +434,7 @@ struct main_type
|
||||||
|
unsigned int flag_vector : 1;
|
||||||
|
unsigned int flag_stub_supported : 1;
|
||||||
|
unsigned int flag_nottext : 1;
|
||||||
|
+ unsigned int flag_gnu_ifunc : 1;
|
||||||
|
unsigned int flag_fixed_instance : 1;
|
||||||
|
unsigned int flag_objfile_owned : 1;
|
||||||
|
unsigned int flag_discardable : 1;
|
||||||
|
@@ -1144,6 +1152,10 @@ struct builtin_type
|
||||||
|
(*) () can server as a generic function pointer. */
|
||||||
|
struct type *builtin_func_ptr;
|
||||||
|
|
||||||
|
+ /* `pointer to function returning pointer to function (returning void)' type.
|
||||||
|
+ The final void return type is not significant for it. */
|
||||||
|
+ struct type *builtin_func_func_ptr;
|
||||||
|
+
|
||||||
|
|
||||||
|
/* Special-purpose types. */
|
||||||
|
|
||||||
|
@@ -1186,6 +1198,7 @@ struct objfile_type
|
||||||
|
|
||||||
|
/* Types used for symbols with no debug information. */
|
||||||
|
struct type *nodebug_text_symbol;
|
||||||
|
+ struct type *nodebug_text_gnu_ifunc_symbol;
|
||||||
|
struct type *nodebug_data_symbol;
|
||||||
|
struct type *nodebug_unknown_symbol;
|
||||||
|
struct type *nodebug_tls_symbol;
|
||||||
|
Index: gdb-7.0/gdb/infcall.c
|
||||||
|
===================================================================
|
||||||
|
--- gdb-7.0.orig/gdb/infcall.c 2009-11-25 10:24:45.000000000 +0100
|
||||||
|
+++ gdb-7.0/gdb/infcall.c 2009-11-25 10:24:56.000000000 +0100
|
||||||
|
@@ -286,6 +286,27 @@ find_function_addr (struct value *functi
|
||||||
|
else
|
||||||
|
error (_("Invalid data type for function to be called."));
|
||||||
|
|
||||||
|
+ if (TYPE_GNU_IFUNC (ftype))
|
||||||
|
+ {
|
||||||
|
+ struct type *func_func_ptr;
|
||||||
|
+
|
||||||
|
+ funaddr += gdbarch_deprecated_function_start_offset (gdbarch);
|
||||||
|
+
|
||||||
|
+ /* Cast FUNADDR to drop TYPE_GNU_IFUNC and being able to call gnu-ifunc
|
||||||
|
+ FUNADDR without causing deadlock by this block of code. */
|
||||||
|
+
|
||||||
|
+ func_func_ptr = builtin_type (gdbarch)->builtin_func_func_ptr;
|
||||||
|
+ function = value_from_pointer (func_func_ptr, funaddr);
|
||||||
|
+
|
||||||
|
+ /* gnu-ifuncs have no arguments. */
|
||||||
|
+ function = call_function_by_hand (function, 0, NULL);
|
||||||
|
+
|
||||||
|
+ funaddr = value_as_address (function);
|
||||||
|
+
|
||||||
|
+ /* This is `int' as the return type of the final function. */
|
||||||
|
+ value_type = TYPE_TARGET_TYPE (value_type);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (retval_type != NULL)
|
||||||
|
*retval_type = value_type;
|
||||||
|
return funaddr + gdbarch_deprecated_function_start_offset (gdbarch);
|
||||||
|
Index: gdb-7.0/gdb/linespec.c
|
||||||
|
===================================================================
|
||||||
|
--- gdb-7.0.orig/gdb/linespec.c 2009-11-25 10:24:45.000000000 +0100
|
||||||
|
+++ gdb-7.0/gdb/linespec.c 2009-11-25 10:24:56.000000000 +0100
|
||||||
|
@@ -40,6 +40,7 @@
|
||||||
|
#include "interps.h"
|
||||||
|
#include "mi/mi-cmds.h"
|
||||||
|
#include "target.h"
|
||||||
|
+#include "infcall.h"
|
||||||
|
|
||||||
|
/* We share this one with symtab.c, but it is not exported widely. */
|
||||||
|
|
||||||
|
@@ -1875,6 +1876,22 @@ minsym_found (int funfirstline, struct m
|
||||||
|
pc = gdbarch_convert_from_func_ptr_addr (gdbarch,
|
||||||
|
values.sals[0].pc,
|
||||||
|
¤t_target);
|
||||||
|
+
|
||||||
|
+ /* Call gnu-ifunc to resolve breakpoint at its returned function. */
|
||||||
|
+ if (MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc)
|
||||||
|
+ {
|
||||||
|
+ struct type *func_func_ptr;
|
||||||
|
+ struct value *function;
|
||||||
|
+
|
||||||
|
+ func_func_ptr = builtin_type (gdbarch)->builtin_func_func_ptr;
|
||||||
|
+ function = value_from_pointer (func_func_ptr, pc);
|
||||||
|
+
|
||||||
|
+ /* gnu-ifuncs have no arguments. */
|
||||||
|
+ function = call_function_by_hand (function, 0, NULL);
|
||||||
|
+
|
||||||
|
+ pc = value_as_address (function);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (pc != values.sals[0].pc)
|
||||||
|
values.sals[0] = find_pc_sect_line (pc, NULL, 0);
|
||||||
|
|
||||||
|
Index: gdb-7.0/gdb/minsyms.c
|
||||||
|
===================================================================
|
||||||
|
--- gdb-7.0.orig/gdb/minsyms.c 2009-11-25 10:24:47.000000000 +0100
|
||||||
|
+++ gdb-7.0/gdb/minsyms.c 2009-11-25 10:24:56.000000000 +0100
|
||||||
|
@@ -331,8 +331,9 @@ lookup_minimal_symbol_text (const char *
|
||||||
|
msymbol = msymbol->hash_next)
|
||||||
|
{
|
||||||
|
if (strcmp (SYMBOL_LINKAGE_NAME (msymbol), name) == 0 &&
|
||||||
|
- (MSYMBOL_TYPE (msymbol) == mst_text ||
|
||||||
|
- MSYMBOL_TYPE (msymbol) == mst_file_text))
|
||||||
|
+ (MSYMBOL_TYPE (msymbol) == mst_text
|
||||||
|
+ || MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc
|
||||||
|
+ || MSYMBOL_TYPE (msymbol) == mst_file_text))
|
||||||
|
{
|
||||||
|
switch (MSYMBOL_TYPE (msymbol))
|
||||||
|
{
|
||||||
|
@@ -699,6 +700,16 @@ lookup_minimal_symbol_by_pc (CORE_ADDR p
|
||||||
|
{
|
||||||
|
return lookup_minimal_symbol_by_pc_section (pc, NULL);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+/* Return non-zero iff PC is in function implementing gnu-ifunc selection. */
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+in_gnu_ifunc_stub (CORE_ADDR pc)
|
||||||
|
+{
|
||||||
|
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (pc);
|
||||||
|
+
|
||||||
|
+ return msymbol && MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc;
|
||||||
|
+}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return leading symbol character for a BFD. If BFD is NULL,
|
||||||
|
@@ -738,6 +749,7 @@ prim_record_minimal_symbol (const char *
|
||||||
|
switch (ms_type)
|
||||||
|
{
|
||||||
|
case mst_text:
|
||||||
|
+ case mst_text_gnu_ifunc:
|
||||||
|
case mst_file_text:
|
||||||
|
case mst_solib_trampoline:
|
||||||
|
section = SECT_OFF_TEXT (objfile);
|
||||||
|
@@ -1184,7 +1196,8 @@ find_solib_trampoline_target (struct fra
|
||||||
|
{
|
||||||
|
ALL_MSYMBOLS (objfile, msymbol)
|
||||||
|
{
|
||||||
|
- if (MSYMBOL_TYPE (msymbol) == mst_text
|
||||||
|
+ if ((MSYMBOL_TYPE (msymbol) == mst_text
|
||||||
|
+ || MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc)
|
||||||
|
&& strcmp (SYMBOL_LINKAGE_NAME (msymbol),
|
||||||
|
SYMBOL_LINKAGE_NAME (tsymbol)) == 0)
|
||||||
|
return SYMBOL_VALUE_ADDRESS (msymbol);
|
||||||
|
Index: gdb-7.0/gdb/parse.c
|
||||||
|
===================================================================
|
||||||
|
--- gdb-7.0.orig/gdb/parse.c 2009-11-25 10:24:47.000000000 +0100
|
||||||
|
+++ gdb-7.0/gdb/parse.c 2009-11-25 10:26:16.000000000 +0100
|
||||||
|
@@ -517,6 +517,11 @@ write_exp_msymbol (struct minimal_symbol
|
||||||
|
write_exp_elt_type (objfile_type (objfile)->nodebug_text_symbol);
|
||||||
|
break;
|
||||||
|
|
||||||
|
+ case mst_text_gnu_ifunc:
|
||||||
|
+ write_exp_elt_type (objfile_type (objfile)
|
||||||
|
+ ->nodebug_text_gnu_ifunc_symbol);
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
case mst_data:
|
||||||
|
case mst_file_data:
|
||||||
|
case mst_bss:
|
||||||
|
Index: gdb-7.0/gdb/solib-svr4.c
|
||||||
|
===================================================================
|
||||||
|
--- gdb-7.0.orig/gdb/solib-svr4.c 2009-11-25 10:24:49.000000000 +0100
|
||||||
|
+++ gdb-7.0/gdb/solib-svr4.c 2009-11-25 10:26:41.000000000 +0100
|
||||||
|
@@ -1242,7 +1242,8 @@ svr4_in_dynsym_resolve_code (CORE_ADDR p
|
||||||
|
{
|
||||||
|
return ((pc >= interp_text_sect_low && pc < interp_text_sect_high)
|
||||||
|
|| (pc >= interp_plt_sect_low && pc < interp_plt_sect_high)
|
||||||
|
- || in_plt_section (pc, NULL));
|
||||||
|
+ || in_plt_section (pc, NULL)
|
||||||
|
+ || in_gnu_ifunc_stub (pc));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Given an executable's ABFD and target, compute the entry-point
|
||||||
|
Index: gdb-7.0/gdb/symmisc.c
|
||||||
|
===================================================================
|
||||||
|
--- gdb-7.0.orig/gdb/symmisc.c 2009-11-25 10:24:47.000000000 +0100
|
||||||
|
+++ gdb-7.0/gdb/symmisc.c 2009-11-25 10:24:56.000000000 +0100
|
||||||
|
@@ -287,6 +287,9 @@ dump_msymbols (struct objfile *objfile,
|
||||||
|
case mst_text:
|
||||||
|
ms_type = 'T';
|
||||||
|
break;
|
||||||
|
+ case mst_text_gnu_ifunc:
|
||||||
|
+ ms_type = 'i';
|
||||||
|
+ break;
|
||||||
|
case mst_solib_trampoline:
|
||||||
|
ms_type = 'S';
|
||||||
|
break;
|
||||||
|
Index: gdb-7.0/gdb/symtab.c
|
||||||
|
===================================================================
|
||||||
|
--- gdb-7.0.orig/gdb/symtab.c 2009-11-25 10:24:47.000000000 +0100
|
||||||
|
+++ gdb-7.0/gdb/symtab.c 2009-11-25 10:24:56.000000000 +0100
|
||||||
|
@@ -3155,7 +3155,7 @@ search_symbols (char *regexp, domain_enu
|
||||||
|
{mst_file_data, mst_solib_trampoline, mst_abs, mst_unknown};
|
||||||
|
static enum minimal_symbol_type types4[]
|
||||||
|
=
|
||||||
|
- {mst_file_bss, mst_text, mst_abs, mst_unknown};
|
||||||
|
+ {mst_file_bss, mst_text_gnu_ifunc, mst_abs, mst_unknown};
|
||||||
|
enum minimal_symbol_type ourtype;
|
||||||
|
enum minimal_symbol_type ourtype2;
|
||||||
|
enum minimal_symbol_type ourtype3;
|
||||||
|
Index: gdb-7.0/gdb/symtab.h
|
||||||
|
===================================================================
|
||||||
|
--- gdb-7.0.orig/gdb/symtab.h 2009-11-25 10:24:45.000000000 +0100
|
||||||
|
+++ gdb-7.0/gdb/symtab.h 2009-11-25 10:24:56.000000000 +0100
|
||||||
|
@@ -275,6 +275,8 @@ enum minimal_symbol_type
|
||||||
|
{
|
||||||
|
mst_unknown = 0, /* Unknown type, the default */
|
||||||
|
mst_text, /* Generally executable instructions */
|
||||||
|
+ mst_text_gnu_ifunc, /* Executable code returning address
|
||||||
|
+ of executable code */
|
||||||
|
mst_data, /* Generally initialized data */
|
||||||
|
mst_bss, /* Generally uninitialized data */
|
||||||
|
mst_abs, /* Generally absolute (nonrelocatable) */
|
||||||
|
@@ -1149,6 +1151,8 @@ extern struct minimal_symbol *lookup_min
|
||||||
|
|
||||||
|
extern struct minimal_symbol *lookup_minimal_symbol_by_pc (CORE_ADDR);
|
||||||
|
|
||||||
|
+extern int in_gnu_ifunc_stub (CORE_ADDR pc);
|
||||||
|
+
|
||||||
|
extern struct minimal_symbol
|
||||||
|
*lookup_minimal_symbol_by_pc_section (CORE_ADDR, struct obj_section *);
|
||||||
|
|
||||||
|
Index: gdb-7.0/gdb/testsuite/gdb.base/gnu-ifunc-lib.c
|
||||||
|
===================================================================
|
||||||
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||||||
|
+++ gdb-7.0/gdb/testsuite/gdb.base/gnu-ifunc-lib.c 2009-11-25 10:24:56.000000000 +0100
|
||||||
|
@@ -0,0 +1,45 @@
|
||||||
|
+/* This testcase is part of GDB, the GNU debugger.
|
||||||
|
+
|
||||||
|
+ Copyright 2009 Free Software Foundation, Inc.
|
||||||
|
+
|
||||||
|
+ This program is free software; you can redistribute it and/or modify
|
||||||
|
+ it under the terms of the GNU General Public License as published by
|
||||||
|
+ the Free Software Foundation; either version 3 of the License, or
|
||||||
|
+ (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ This program is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ GNU General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU General Public License
|
||||||
|
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <assert.h>
|
||||||
|
+
|
||||||
|
+typedef int (*final_t) (int arg);
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+final (int arg)
|
||||||
|
+{
|
||||||
|
+ return arg + 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static volatile int gnu_ifunc_initialized;
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+gnu_ifunc_pre (void)
|
||||||
|
+{
|
||||||
|
+ assert (!gnu_ifunc_initialized);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+final_t gnu_ifuncX (void) asm ("gnu_ifunc");
|
||||||
|
+asm (".type gnu_ifunc, @gnu_indirect_function");
|
||||||
|
+
|
||||||
|
+final_t
|
||||||
|
+gnu_ifuncX (void)
|
||||||
|
+{
|
||||||
|
+ gnu_ifunc_initialized = 1;
|
||||||
|
+
|
||||||
|
+ return final;
|
||||||
|
+}
|
||||||
|
Index: gdb-7.0/gdb/testsuite/gdb.base/gnu-ifunc.c
|
||||||
|
===================================================================
|
||||||
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||||||
|
+++ gdb-7.0/gdb/testsuite/gdb.base/gnu-ifunc.c 2009-11-25 10:24:56.000000000 +0100
|
||||||
|
@@ -0,0 +1,36 @@
|
||||||
|
+/* This testcase is part of GDB, the GNU debugger.
|
||||||
|
+
|
||||||
|
+ Copyright 2009 Free Software Foundation, Inc.
|
||||||
|
+
|
||||||
|
+ This program is free software; you can redistribute it and/or modify
|
||||||
|
+ it under the terms of the GNU General Public License as published by
|
||||||
|
+ the Free Software Foundation; either version 3 of the License, or
|
||||||
|
+ (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ This program is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ GNU General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU General Public License
|
||||||
|
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <assert.h>
|
||||||
|
+
|
||||||
|
+extern int gnu_ifunc (int arg);
|
||||||
|
+extern void gnu_ifunc_pre (void);
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+main (void)
|
||||||
|
+{
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ gnu_ifunc_pre ();
|
||||||
|
+
|
||||||
|
+ i = gnu_ifunc (1); /* break-at-call */
|
||||||
|
+ assert (i == 2);
|
||||||
|
+
|
||||||
|
+ gnu_ifunc (2); /* break-at-nextcall */
|
||||||
|
+
|
||||||
|
+ return 0; /* break-at-exit */
|
||||||
|
+}
|
||||||
|
Index: gdb-7.0/gdb/testsuite/gdb.base/gnu-ifunc.exp
|
||||||
|
===================================================================
|
||||||
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||||||
|
+++ gdb-7.0/gdb/testsuite/gdb.base/gnu-ifunc.exp 2009-11-25 10:24:56.000000000 +0100
|
||||||
|
@@ -0,0 +1,72 @@
|
||||||
|
+# Copyright (C) 2009 Free Software Foundation, Inc.
|
||||||
|
+
|
||||||
|
+# This program is free software; you can redistribute it and/or modify
|
||||||
|
+# it under the terms of the GNU General Public License as published by
|
||||||
|
+# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
+# (at your option) any later version.
|
||||||
|
+#
|
||||||
|
+# This program is distributed in the hope that it will be useful,
|
||||||
|
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+# GNU General Public License for more details.
|
||||||
|
+#
|
||||||
|
+# You should have received a copy of the GNU General Public License
|
||||||
|
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
+
|
||||||
|
+if {[skip_shlib_tests]} {
|
||||||
|
+ return 0
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+set testfile "gnu-ifunc"
|
||||||
|
+set srcfile ${testfile}.c
|
||||||
|
+set binfile ${objdir}/${subdir}/${testfile}
|
||||||
|
+
|
||||||
|
+set libfile "${testfile}-lib"
|
||||||
|
+set libsrc ${libfile}.c
|
||||||
|
+set lib_so ${objdir}/${subdir}/${libfile}.so
|
||||||
|
+
|
||||||
|
+set lib_opts [list debug]
|
||||||
|
+set exec_opts [list debug shlib=$lib_so]
|
||||||
|
+
|
||||||
|
+if [get_compiler_info ${binfile}] {
|
||||||
|
+ return -1
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+if { [gdb_compile_shlib ${srcdir}/${subdir}/$libsrc $lib_so $lib_opts] != ""
|
||||||
|
+ || [gdb_compile ${srcdir}/${subdir}/$srcfile $binfile executable $exec_opts] != ""} {
|
||||||
|
+ untested "Could not compile either $libsrc or $srcfile."
|
||||||
|
+ return -1
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+# Start with a fresh gdb.
|
||||||
|
+
|
||||||
|
+clean_restart $testfile
|
||||||
|
+gdb_load_shlibs ${lib_so}
|
||||||
|
+
|
||||||
|
+if ![runto_main] then {
|
||||||
|
+ fail "Can't run to main"
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+gdb_breakpoint [gdb_get_line_number "break-at-nextcall"]
|
||||||
|
+
|
||||||
|
+gdb_breakpoint [gdb_get_line_number "break-at-call"]
|
||||||
|
+gdb_continue_to_breakpoint "break-at-call" ".*break-at-call.*"
|
||||||
|
+
|
||||||
|
+# Test GDB will automatically indirect the call.
|
||||||
|
+
|
||||||
|
+gdb_test "p gnu_ifunc (3)" " = 4"
|
||||||
|
+
|
||||||
|
+# Test GDB will skip the gnu_ifunc resolver on first call.
|
||||||
|
+
|
||||||
|
+gdb_test "step" "\r\nfinal .*"
|
||||||
|
+
|
||||||
|
+# Test GDB will not break before the final chosen implementation.
|
||||||
|
+
|
||||||
|
+gdb_continue_to_breakpoint "break-at-nextcall" ".*break-at-nextcall.*"
|
||||||
|
+
|
||||||
|
+gdb_breakpoint "gnu_ifunc"
|
||||||
|
+
|
||||||
|
+gdb_continue_to_breakpoint "nextcall gnu_ifunc"
|
||||||
|
+
|
||||||
|
+gdb_test "frame" "#0 +final \\(.*" "nextcall gnu_ifunc skipped"
|
15
gdb.spec
15
gdb.spec
@ -14,7 +14,7 @@ Version: 7.0
|
|||||||
|
|
||||||
# The release always contains a leading reserved number, start it at 1.
|
# The release always contains a leading reserved number, start it at 1.
|
||||||
# `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing.
|
# `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing.
|
||||||
Release: 6%{?_with_upstream:.upstream}%{?dist}
|
Release: 7%{?_with_upstream:.upstream}%{?dist}
|
||||||
|
|
||||||
License: GPLv3+
|
License: GPLv3+
|
||||||
Group: Development/Debuggers
|
Group: Development/Debuggers
|
||||||
@ -371,6 +371,12 @@ Patch383: gdb-bz528668-symfile-sepcrc.patch
|
|||||||
Patch384: gdb-bz528668-symfile-cleanup.patch
|
Patch384: gdb-bz528668-symfile-cleanup.patch
|
||||||
Patch385: gdb-bz528668-symfile-multi.patch
|
Patch385: gdb-bz528668-symfile-multi.patch
|
||||||
|
|
||||||
|
# Support GNU IFUNCs - indirect functions (BZ 539590).
|
||||||
|
Patch387: gdb-bz539590-gnu-ifunc.patch
|
||||||
|
|
||||||
|
# Fix bp conditionals [bp_location-accel] regression (Phil Muldoon, BZ 538626).
|
||||||
|
Patch388: gdb-bz538626-bp_location-accel-bp-cond.patch
|
||||||
|
|
||||||
BuildRequires: ncurses-devel texinfo gettext flex bison expat-devel
|
BuildRequires: ncurses-devel texinfo gettext flex bison expat-devel
|
||||||
Requires: readline
|
Requires: readline
|
||||||
BuildRequires: readline-devel
|
BuildRequires: readline-devel
|
||||||
@ -571,6 +577,8 @@ rm -f gdb/jv-exp.c gdb/m2-exp.c gdb/objc-exp.c gdb/p-exp.c
|
|||||||
%patch376 -p1
|
%patch376 -p1
|
||||||
%patch381 -p1
|
%patch381 -p1
|
||||||
%patch382 -p1
|
%patch382 -p1
|
||||||
|
%patch387 -p1
|
||||||
|
%patch388 -p1
|
||||||
%patch124 -p1
|
%patch124 -p1
|
||||||
|
|
||||||
find -name "*.orig" | xargs rm -f
|
find -name "*.orig" | xargs rm -f
|
||||||
@ -876,6 +884,11 @@ fi
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Wed Nov 25 2009 Jan Kratochvil <jan.kratochvil@redhat.com> - 7.0-7.fc12
|
||||||
|
- Support GNU IFUNCs - indirect functions (BZ 539590).
|
||||||
|
- Fix bp conditionals [bp_location-accel] regression (Phil Muldoon, BZ 538626).
|
||||||
|
- Fix missed breakpoint location [bp_location-accel] regression (upstream).
|
||||||
|
|
||||||
* Fri Oct 30 2009 Jan Kratochvil <jan.kratochvil@redhat.com> - 7.0-6
|
* Fri Oct 30 2009 Jan Kratochvil <jan.kratochvil@redhat.com> - 7.0-6
|
||||||
- Fix missing zlib-devel BuildRequires to support compressed DWARF sections.
|
- Fix missing zlib-devel BuildRequires to support compressed DWARF sections.
|
||||||
- Include post-7.0 FSF GDB fixes.
|
- Include post-7.0 FSF GDB fixes.
|
||||||
|
Loading…
Reference in New Issue
Block a user