@@ -59,6 +59,31 @@ static struct instruction *next_insn_same_sec(struct objtool_file *file,
5959 return next ;
6060}
6161
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+
6287#define func_for_each_insn (file , func , insn ) \
6388 for (insn = find_insn(file, func->sec, func->offset); \
6489 insn && &insn->list != &file->insn_list && \
@@ -149,10 +174,14 @@ static int __dead_end_function(struct objtool_file *file, struct symbol *func,
149174 if (!strcmp (func -> name , global_noreturns [i ]))
150175 return 1 ;
151176
152- if (!func -> sec )
177+ if (!func -> len )
153178 return 0 ;
154179
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 ) {
156185 empty = false;
157186
158187 if (insn -> type == INSN_RETURN )
@@ -167,28 +196,17 @@ static int __dead_end_function(struct objtool_file *file, struct symbol *func,
167196 * case, the function's dead-end status depends on whether the target
168197 * of the sibling call returns.
169198 */
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 ) {
175200 if (insn -> type == INSN_JUMP_UNCONDITIONAL ) {
176201 struct instruction * dest = insn -> jump_dest ;
177- struct symbol * dest_func ;
178202
179203 if (!dest )
180204 /* sibling call to another file */
181205 return 0 ;
182206
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 ) {
191208
209+ /* local sibling call */
192210 if (recursion == 5 ) {
193211 /*
194212 * Infinite recursion: two functions
@@ -199,7 +217,7 @@ static int __dead_end_function(struct objtool_file *file, struct symbol *func,
199217 return 0 ;
200218 }
201219
202- return __dead_end_function (file , dest_func ,
220+ return __dead_end_function (file , dest -> func ,
203221 recursion + 1 );
204222 }
205223 }
@@ -426,7 +444,7 @@ static void add_ignores(struct objtool_file *file)
426444 if (!ignore_func (file , func ))
427445 continue ;
428446
429- func_for_each_insn (file , func , insn )
447+ func_for_each_insn_all (file , func , insn )
430448 insn -> ignore = true;
431449 }
432450 }
@@ -786,9 +804,8 @@ static int add_special_section_alts(struct objtool_file *file)
786804 return ret ;
787805}
788806
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 )
792809{
793810 struct rela * rela = table ;
794811 struct instruction * alt_insn ;
@@ -798,18 +815,13 @@ static int add_switch_table(struct objtool_file *file, struct symbol *func,
798815 if (rela == next_table )
799816 break ;
800817
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 )
804820 break ;
805821
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 ;
813825
814826 alt = malloc (sizeof (* alt ));
815827 if (!alt ) {
@@ -947,7 +959,7 @@ static int add_func_switch_tables(struct objtool_file *file,
947959 struct rela * rela , * prev_rela = NULL ;
948960 int ret ;
949961
950- func_for_each_insn (file , func , insn ) {
962+ func_for_each_insn_all (file , func , insn ) {
951963 if (!last )
952964 last = insn ;
953965
@@ -978,8 +990,7 @@ static int add_func_switch_tables(struct objtool_file *file,
978990 * the beginning of another switch table in the same function.
979991 */
980992 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 );
983994 if (ret )
984995 return ret ;
985996 }
@@ -989,7 +1000,7 @@ static int add_func_switch_tables(struct objtool_file *file,
9891000 }
9901001
9911002 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 );
9931004 if (ret )
9941005 return ret ;
9951006 }
@@ -1753,15 +1764,13 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
17531764 while (1 ) {
17541765 next_insn = next_insn_same_sec (file , insn );
17551766
1756-
1757- if (file -> c_file && func && insn -> func && func != insn -> func ) {
1767+ if (file -> c_file && func && insn -> func && func != insn -> func -> pfunc ) {
17581768 WARN ("%s() falls through to next function %s()" ,
17591769 func -> name , insn -> func -> name );
17601770 return 1 ;
17611771 }
17621772
1763- if (insn -> func )
1764- func = insn -> func ;
1773+ func = insn -> func ? insn -> func -> pfunc : NULL ;
17651774
17661775 if (func && insn -> ignore ) {
17671776 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,
17821791
17831792 i = insn ;
17841793 save_insn = NULL ;
1785- func_for_each_insn_continue_reverse (file , func , i ) {
1794+ func_for_each_insn_continue_reverse (file , insn -> func , i ) {
17861795 if (i -> save ) {
17871796 save_insn = i ;
17881797 break ;
@@ -1869,7 +1878,7 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
18691878 case INSN_JUMP_UNCONDITIONAL :
18701879 if (insn -> jump_dest &&
18711880 (!func || !insn -> jump_dest -> func ||
1872- func == insn -> jump_dest -> func )) {
1881+ insn -> jump_dest -> func -> pfunc == func )) {
18731882 ret = validate_branch (file , insn -> jump_dest ,
18741883 state );
18751884 if (ret )
@@ -2064,7 +2073,7 @@ static int validate_functions(struct objtool_file *file)
20642073
20652074 for_each_sec (file , sec ) {
20662075 list_for_each_entry (func , & sec -> symbol_list , list ) {
2067- if (func -> type != STT_FUNC )
2076+ if (func -> type != STT_FUNC || func -> pfunc != func )
20682077 continue ;
20692078
20702079 insn = find_insn (file , sec , func -> offset );
0 commit comments