@@ -59,6 +59,31 @@ static struct instruction *next_insn_same_sec(struct objtool_file *file,
59
59
return next ;
60
60
}
61
61
62
+ static struct instruction * next_insn_same_func (struct objtool_file * file ,
63
+ struct instruction * insn )
64
+ {
65
+ struct instruction * next = list_next_entry (insn , list );
66
+ struct symbol * func = insn -> func ;
67
+
68
+ if (!func )
69
+ return NULL ;
70
+
71
+ if (& next -> list != & file -> insn_list && next -> func == func )
72
+ return next ;
73
+
74
+ /* Check if we're already in the subfunction: */
75
+ if (func == func -> cfunc )
76
+ return NULL ;
77
+
78
+ /* Move to the subfunction: */
79
+ return find_insn (file , func -> cfunc -> sec , func -> cfunc -> offset );
80
+ }
81
+
82
+ #define func_for_each_insn_all (file , func , insn ) \
83
+ for (insn = find_insn(file, func->sec, func->offset); \
84
+ insn; \
85
+ insn = next_insn_same_func(file, insn))
86
+
62
87
#define func_for_each_insn (file , func , insn ) \
63
88
for (insn = find_insn(file, func->sec, func->offset); \
64
89
insn && &insn->list != &file->insn_list && \
@@ -149,10 +174,14 @@ static int __dead_end_function(struct objtool_file *file, struct symbol *func,
149
174
if (!strcmp (func -> name , global_noreturns [i ]))
150
175
return 1 ;
151
176
152
- if (!func -> sec )
177
+ if (!func -> len )
153
178
return 0 ;
154
179
155
- func_for_each_insn (file , func , insn ) {
180
+ insn = find_insn (file , func -> sec , func -> offset );
181
+ if (!insn -> func )
182
+ return 0 ;
183
+
184
+ func_for_each_insn_all (file , func , insn ) {
156
185
empty = false;
157
186
158
187
if (insn -> type == INSN_RETURN )
@@ -167,28 +196,17 @@ static int __dead_end_function(struct objtool_file *file, struct symbol *func,
167
196
* case, the function's dead-end status depends on whether the target
168
197
* of the sibling call returns.
169
198
*/
170
- func_for_each_insn (file , func , insn ) {
171
- if (insn -> sec != func -> sec ||
172
- insn -> offset >= func -> offset + func -> len )
173
- break ;
174
-
199
+ func_for_each_insn_all (file , func , insn ) {
175
200
if (insn -> type == INSN_JUMP_UNCONDITIONAL ) {
176
201
struct instruction * dest = insn -> jump_dest ;
177
- struct symbol * dest_func ;
178
202
179
203
if (!dest )
180
204
/* sibling call to another file */
181
205
return 0 ;
182
206
183
- if (dest -> sec != func -> sec ||
184
- dest -> offset < func -> offset ||
185
- dest -> offset >= func -> offset + func -> len ) {
186
- /* local sibling call */
187
- dest_func = find_symbol_by_offset (dest -> sec ,
188
- dest -> offset );
189
- if (!dest_func )
190
- continue ;
207
+ if (dest -> func && dest -> func -> pfunc != insn -> func -> pfunc ) {
191
208
209
+ /* local sibling call */
192
210
if (recursion == 5 ) {
193
211
/*
194
212
* Infinite recursion: two functions
@@ -199,7 +217,7 @@ static int __dead_end_function(struct objtool_file *file, struct symbol *func,
199
217
return 0 ;
200
218
}
201
219
202
- return __dead_end_function (file , dest_func ,
220
+ return __dead_end_function (file , dest -> func ,
203
221
recursion + 1 );
204
222
}
205
223
}
@@ -426,7 +444,7 @@ static void add_ignores(struct objtool_file *file)
426
444
if (!ignore_func (file , func ))
427
445
continue ;
428
446
429
- func_for_each_insn (file , func , insn )
447
+ func_for_each_insn_all (file , func , insn )
430
448
insn -> ignore = true;
431
449
}
432
450
}
@@ -786,9 +804,8 @@ static int add_special_section_alts(struct objtool_file *file)
786
804
return ret ;
787
805
}
788
806
789
- static int add_switch_table (struct objtool_file * file , struct symbol * func ,
790
- struct instruction * insn , struct rela * table ,
791
- struct rela * next_table )
807
+ static int add_switch_table (struct objtool_file * file , struct instruction * insn ,
808
+ struct rela * table , struct rela * next_table )
792
809
{
793
810
struct rela * rela = table ;
794
811
struct instruction * alt_insn ;
@@ -798,18 +815,13 @@ static int add_switch_table(struct objtool_file *file, struct symbol *func,
798
815
if (rela == next_table )
799
816
break ;
800
817
801
- if (rela -> sym -> sec != insn -> sec ||
802
- rela -> addend <= func -> offset ||
803
- rela -> addend >= func -> offset + func -> len )
818
+ alt_insn = find_insn (file , rela -> sym -> sec , rela -> addend );
819
+ if (!alt_insn )
804
820
break ;
805
821
806
- alt_insn = find_insn (file , insn -> sec , rela -> addend );
807
- if (!alt_insn ) {
808
- WARN ("%s: can't find instruction at %s+0x%x" ,
809
- file -> rodata -> rela -> name , insn -> sec -> name ,
810
- rela -> addend );
811
- return -1 ;
812
- }
822
+ /* Make sure the jmp dest is in the function or subfunction: */
823
+ if (alt_insn -> func -> pfunc != insn -> func -> pfunc )
824
+ break ;
813
825
814
826
alt = malloc (sizeof (* alt ));
815
827
if (!alt ) {
@@ -947,7 +959,7 @@ static int add_func_switch_tables(struct objtool_file *file,
947
959
struct rela * rela , * prev_rela = NULL ;
948
960
int ret ;
949
961
950
- func_for_each_insn (file , func , insn ) {
962
+ func_for_each_insn_all (file , func , insn ) {
951
963
if (!last )
952
964
last = insn ;
953
965
@@ -978,8 +990,7 @@ static int add_func_switch_tables(struct objtool_file *file,
978
990
* the beginning of another switch table in the same function.
979
991
*/
980
992
if (prev_jump ) {
981
- ret = add_switch_table (file , func , prev_jump , prev_rela ,
982
- rela );
993
+ ret = add_switch_table (file , prev_jump , prev_rela , rela );
983
994
if (ret )
984
995
return ret ;
985
996
}
@@ -989,7 +1000,7 @@ static int add_func_switch_tables(struct objtool_file *file,
989
1000
}
990
1001
991
1002
if (prev_jump ) {
992
- ret = add_switch_table (file , func , prev_jump , prev_rela , NULL );
1003
+ ret = add_switch_table (file , prev_jump , prev_rela , NULL );
993
1004
if (ret )
994
1005
return ret ;
995
1006
}
@@ -1753,15 +1764,13 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
1753
1764
while (1 ) {
1754
1765
next_insn = next_insn_same_sec (file , insn );
1755
1766
1756
-
1757
- if (file -> c_file && func && insn -> func && func != insn -> func ) {
1767
+ if (file -> c_file && func && insn -> func && func != insn -> func -> pfunc ) {
1758
1768
WARN ("%s() falls through to next function %s()" ,
1759
1769
func -> name , insn -> func -> name );
1760
1770
return 1 ;
1761
1771
}
1762
1772
1763
- if (insn -> func )
1764
- func = insn -> func ;
1773
+ func = insn -> func ? insn -> func -> pfunc : NULL ;
1765
1774
1766
1775
if (func && insn -> ignore ) {
1767
1776
WARN_FUNC ("BUG: why am I validating an ignored function?" ,
@@ -1782,7 +1791,7 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
1782
1791
1783
1792
i = insn ;
1784
1793
save_insn = NULL ;
1785
- func_for_each_insn_continue_reverse (file , func , i ) {
1794
+ func_for_each_insn_continue_reverse (file , insn -> func , i ) {
1786
1795
if (i -> save ) {
1787
1796
save_insn = i ;
1788
1797
break ;
@@ -1869,7 +1878,7 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
1869
1878
case INSN_JUMP_UNCONDITIONAL :
1870
1879
if (insn -> jump_dest &&
1871
1880
(!func || !insn -> jump_dest -> func ||
1872
- func == insn -> jump_dest -> func )) {
1881
+ insn -> jump_dest -> func -> pfunc == func )) {
1873
1882
ret = validate_branch (file , insn -> jump_dest ,
1874
1883
state );
1875
1884
if (ret )
@@ -2064,7 +2073,7 @@ static int validate_functions(struct objtool_file *file)
2064
2073
2065
2074
for_each_sec (file , sec ) {
2066
2075
list_for_each_entry (func , & sec -> symbol_list , list ) {
2067
- if (func -> type != STT_FUNC )
2076
+ if (func -> type != STT_FUNC || func -> pfunc != func )
2068
2077
continue ;
2069
2078
2070
2079
insn = find_insn (file , sec , func -> offset );
0 commit comments