@@ -1497,9 +1497,11 @@ function_addrs_compare (const void *v1, const void *v2)
1497
1497
return strcmp (a1 -> function -> name , a2 -> function -> name );
1498
1498
}
1499
1499
1500
- /* Compare a PC against a function_addrs for bsearch. Note that if
1501
- there are multiple ranges containing PC, which one will be returned
1502
- is unpredictable. We compensate for that in dwarf_fileline. */
1500
+ /* Compare a PC against a function_addrs for bsearch. We always
1501
+ allocate an entra entry at the end of the vector, so that this
1502
+ routine can safely look at the next entry. Note that if there are
1503
+ multiple ranges containing PC, which one will be returned is
1504
+ unpredictable. We compensate for that in dwarf_fileline. */
1503
1505
1504
1506
static int
1505
1507
function_addrs_search (const void * vkey , const void * ventry )
@@ -1511,7 +1513,7 @@ function_addrs_search (const void *vkey, const void *ventry)
1511
1513
pc = * key ;
1512
1514
if (pc < entry -> low )
1513
1515
return -1 ;
1514
- else if (pc >= entry -> high )
1516
+ else if (pc > ( entry + 1 ) -> low )
1515
1517
return 1 ;
1516
1518
else
1517
1519
return 0 ;
@@ -1582,9 +1584,11 @@ unit_addrs_compare (const void *v1, const void *v2)
1582
1584
return 0 ;
1583
1585
}
1584
1586
1585
- /* Compare a PC against a unit_addrs for bsearch. Note that if there
1586
- are multiple ranges containing PC, which one will be returned is
1587
- unpredictable. We compensate for that in dwarf_fileline. */
1587
+ /* Compare a PC against a unit_addrs for bsearch. We always allocate
1588
+ an entry entry at the end of the vector, so that this routine can
1589
+ safely look at the next entry. Note that if there are multiple
1590
+ ranges containing PC, which one will be returned is unpredictable.
1591
+ We compensate for that in dwarf_fileline. */
1588
1592
1589
1593
static int
1590
1594
unit_addrs_search (const void * vkey , const void * ventry )
@@ -1596,7 +1600,7 @@ unit_addrs_search (const void *vkey, const void *ventry)
1596
1600
pc = * key ;
1597
1601
if (pc < entry -> low )
1598
1602
return -1 ;
1599
- else if (pc >= entry -> high )
1603
+ else if (pc > ( entry + 1 ) -> low )
1600
1604
return 1 ;
1601
1605
else
1602
1606
return 0 ;
@@ -2424,6 +2428,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
2424
2428
size_t i ;
2425
2429
struct unit * * pu ;
2426
2430
size_t unit_offset = 0 ;
2431
+ struct unit_addrs * pa ;
2427
2432
2428
2433
memset (& addrs -> vec , 0 , sizeof addrs -> vec );
2429
2434
memset (& unit_vec -> vec , 0 , sizeof unit_vec -> vec );
@@ -2564,6 +2569,17 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
2564
2569
if (info .reported_underflow )
2565
2570
goto fail ;
2566
2571
2572
+ /* Add a trailing addrs entry, but don't include it in addrs->count. */
2573
+ pa = ((struct unit_addrs * )
2574
+ backtrace_vector_grow (state , sizeof (struct unit_addrs ),
2575
+ error_callback , data , & addrs -> vec ));
2576
+ if (pa == NULL )
2577
+ goto fail ;
2578
+ pa -> low = 0 ;
2579
+ -- pa -> low ;
2580
+ pa -> high = pa -> low ;
2581
+ pa -> u = NULL ;
2582
+
2567
2583
unit_vec -> vec = units ;
2568
2584
unit_vec -> count = units_count ;
2569
2585
return 1 ;
@@ -3737,8 +3753,23 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
3737
3753
3738
3754
if (fvec .count > 0 )
3739
3755
{
3756
+ struct function_addrs * p ;
3740
3757
struct function_addrs * faddrs ;
3741
3758
3759
+ /* Allocate a trailing entry, but don't include it
3760
+ in fvec.count. */
3761
+ p = ((struct function_addrs * )
3762
+ backtrace_vector_grow (state ,
3763
+ sizeof (struct function_addrs ),
3764
+ error_callback , data ,
3765
+ & fvec .vec ));
3766
+ if (p == NULL )
3767
+ return 0 ;
3768
+ p -> low = 0 ;
3769
+ -- p -> low ;
3770
+ p -> high = p -> low ;
3771
+ p -> function = NULL ;
3772
+
3742
3773
if (!backtrace_vector_release (state , & fvec .vec ,
3743
3774
error_callback , data ))
3744
3775
return 0 ;
@@ -3772,6 +3803,7 @@ read_function_info (struct backtrace_state *state, struct dwarf_data *ddata,
3772
3803
struct function_vector lvec ;
3773
3804
struct function_vector * pfvec ;
3774
3805
struct dwarf_buf unit_buf ;
3806
+ struct function_addrs * p ;
3775
3807
struct function_addrs * addrs ;
3776
3808
size_t addrs_count ;
3777
3809
@@ -3803,6 +3835,18 @@ read_function_info (struct backtrace_state *state, struct dwarf_data *ddata,
3803
3835
if (pfvec -> count == 0 )
3804
3836
return ;
3805
3837
3838
+ /* Allocate a trailing entry, but don't include it in
3839
+ pfvec->count. */
3840
+ p = ((struct function_addrs * )
3841
+ backtrace_vector_grow (state , sizeof (struct function_addrs ),
3842
+ error_callback , data , & pfvec -> vec ));
3843
+ if (p == NULL )
3844
+ return ;
3845
+ p -> low = 0 ;
3846
+ -- p -> low ;
3847
+ p -> high = p -> low ;
3848
+ p -> function = NULL ;
3849
+
3806
3850
addrs_count = pfvec -> count ;
3807
3851
3808
3852
if (fvec == NULL )
@@ -3839,30 +3883,46 @@ report_inlined_functions (uintptr_t pc, struct function *function,
3839
3883
backtrace_full_callback callback , void * data ,
3840
3884
const char * * filename , int * lineno )
3841
3885
{
3842
- struct function_addrs * function_addrs ;
3886
+ struct function_addrs * p ;
3887
+ struct function_addrs * match ;
3843
3888
struct function * inlined ;
3844
3889
int ret ;
3845
3890
3846
3891
if (function -> function_addrs_count == 0 )
3847
3892
return 0 ;
3848
3893
3849
- function_addrs = ((struct function_addrs * )
3850
- bsearch (& pc , function -> function_addrs ,
3851
- function -> function_addrs_count ,
3852
- sizeof (struct function_addrs ),
3853
- function_addrs_search ));
3854
- if (function_addrs == NULL )
3894
+ p = ((struct function_addrs * )
3895
+ bsearch (& pc , function -> function_addrs ,
3896
+ function -> function_addrs_count ,
3897
+ sizeof (struct function_addrs ),
3898
+ function_addrs_search ));
3899
+ if (p == NULL )
3855
3900
return 0 ;
3856
3901
3857
- while (((size_t ) (function_addrs - function -> function_addrs ) + 1
3858
- < function -> function_addrs_count )
3859
- && pc >= (function_addrs + 1 )-> low
3860
- && pc < (function_addrs + 1 )-> high )
3861
- ++ function_addrs ;
3902
+ /* Here pc >= p->low && pc < (p + 1)->low. The function_addrs are
3903
+ sorted by low, so we are at the end of a range of function_addrs
3904
+ with the same low alue. Walk backward and use the first range
3905
+ that includes pc. */
3906
+ match = NULL ;
3907
+ while (1 )
3908
+ {
3909
+ if (pc < p -> high )
3910
+ {
3911
+ match = p ;
3912
+ break ;
3913
+ }
3914
+ if (p == function -> function_addrs )
3915
+ break ;
3916
+ if ((p - 1 )-> low < p -> low )
3917
+ break ;
3918
+ -- p ;
3919
+ }
3920
+ if (match == NULL )
3921
+ return 0 ;
3862
3922
3863
3923
/* We found an inlined call. */
3864
3924
3865
- inlined = function_addrs -> function ;
3925
+ inlined = match -> function ;
3866
3926
3867
3927
/* Report any calls inlined into this one. */
3868
3928
ret = report_inlined_functions (pc , inlined , callback , data ,
@@ -3895,11 +3955,13 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
3895
3955
int * found )
3896
3956
{
3897
3957
struct unit_addrs * entry ;
3958
+ int found_entry ;
3898
3959
struct unit * u ;
3899
3960
int new_data ;
3900
3961
struct line * lines ;
3901
3962
struct line * ln ;
3902
- struct function_addrs * function_addrs ;
3963
+ struct function_addrs * p ;
3964
+ struct function_addrs * fmatch ;
3903
3965
struct function * function ;
3904
3966
const char * filename ;
3905
3967
int lineno ;
@@ -3919,14 +3981,29 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
3919
3981
return 0 ;
3920
3982
}
3921
3983
3922
- /* If there are multiple ranges that contain PC, use the last one,
3923
- in order to produce predictable results. If we assume that all
3924
- ranges are properly nested, then the last range will be the
3925
- smallest one. */
3926
- while ((size_t ) (entry - ddata -> addrs ) + 1 < ddata -> addrs_count
3927
- && pc >= (entry + 1 )-> low
3928
- && pc < (entry + 1 )-> high )
3929
- ++ entry ;
3984
+ /* Here pc >= entry->low && pc < (entry + 1)->low. The unit_addrs
3985
+ are sorted by low, so we are at the end of a range of unit_addrs
3986
+ with the same low value. Walk backward and use the first range
3987
+ that includes pc. */
3988
+ found_entry = 0 ;
3989
+ while (1 )
3990
+ {
3991
+ if (pc < entry -> high )
3992
+ {
3993
+ found_entry = 1 ;
3994
+ break ;
3995
+ }
3996
+ if (entry == ddata -> addrs )
3997
+ break ;
3998
+ if ((entry - 1 )-> low < entry -> low )
3999
+ break ;
4000
+ -- entry ;
4001
+ }
4002
+ if (!found_entry )
4003
+ {
4004
+ * found = 0 ;
4005
+ return 0 ;
4006
+ }
3930
4007
3931
4008
/* We need the lines, lines_count, function_addrs,
3932
4009
function_addrs_count fields of u. If they are not set, we need
@@ -3962,6 +4039,7 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
3962
4039
new_data = 0 ;
3963
4040
if (lines == NULL )
3964
4041
{
4042
+ struct function_addrs * function_addrs ;
3965
4043
size_t function_addrs_count ;
3966
4044
struct line_header lhdr ;
3967
4045
size_t count ;
@@ -4078,24 +4156,36 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
4078
4156
if (entry -> u -> function_addrs_count == 0 )
4079
4157
return callback (data , pc , ln -> filename , ln -> lineno , NULL );
4080
4158
4081
- function_addrs = ((struct function_addrs * )
4082
- bsearch (& pc , entry -> u -> function_addrs ,
4083
- entry -> u -> function_addrs_count ,
4084
- sizeof (struct function_addrs ),
4085
- function_addrs_search ));
4086
- if (function_addrs == NULL )
4159
+ p = ((struct function_addrs * )
4160
+ bsearch (& pc , entry -> u -> function_addrs ,
4161
+ entry -> u -> function_addrs_count ,
4162
+ sizeof (struct function_addrs ),
4163
+ function_addrs_search ));
4164
+ if (p == NULL )
4087
4165
return callback (data , pc , ln -> filename , ln -> lineno , NULL );
4088
4166
4089
- /* If there are multiple function ranges that contain PC, use the
4090
- last one, in order to produce predictable results. */
4091
-
4092
- while (((size_t ) (function_addrs - entry -> u -> function_addrs + 1 )
4093
- < entry -> u -> function_addrs_count )
4094
- && pc >= (function_addrs + 1 )-> low
4095
- && pc < (function_addrs + 1 )-> high )
4096
- ++ function_addrs ;
4167
+ /* Here pc >= p->low && pc < (p + 1)->low. The function_addrs are
4168
+ sorted by low, so we are at the end of a range of function_addrs
4169
+ with the same low alue. Walk backward and use the first range
4170
+ that includes pc. */
4171
+ fmatch = NULL ;
4172
+ while (1 )
4173
+ {
4174
+ if (pc < p -> high )
4175
+ {
4176
+ fmatch = p ;
4177
+ break ;
4178
+ }
4179
+ if (p == entry -> u -> function_addrs )
4180
+ break ;
4181
+ if ((p - 1 )-> low < p -> low )
4182
+ break ;
4183
+ -- p ;
4184
+ }
4185
+ if (fmatch == NULL )
4186
+ return callback (data , pc , ln -> filename , ln -> lineno , NULL );
4097
4187
4098
- function = function_addrs -> function ;
4188
+ function = fmatch -> function ;
4099
4189
4100
4190
filename = ln -> filename ;
4101
4191
lineno = ln -> lineno ;
0 commit comments