@@ -747,6 +747,52 @@ static int create_retpoline_sites_sections(struct objtool_file *file)
747747 return 0 ;
748748}
749749
750+ static int create_return_sites_sections (struct objtool_file * file )
751+ {
752+ struct instruction * insn ;
753+ struct section * sec ;
754+ int idx ;
755+
756+ sec = find_section_by_name (file -> elf , ".return_sites" );
757+ if (sec ) {
758+ WARN ("file already has .return_sites, skipping" );
759+ return 0 ;
760+ }
761+
762+ idx = 0 ;
763+ list_for_each_entry (insn , & file -> return_thunk_list , call_node )
764+ idx ++ ;
765+
766+ if (!idx )
767+ return 0 ;
768+
769+ sec = elf_create_section (file -> elf , ".return_sites" , 0 ,
770+ sizeof (int ), idx );
771+ if (!sec ) {
772+ WARN ("elf_create_section: .return_sites" );
773+ return -1 ;
774+ }
775+
776+ idx = 0 ;
777+ list_for_each_entry (insn , & file -> return_thunk_list , call_node ) {
778+
779+ int * site = (int * )sec -> data -> d_buf + idx ;
780+ * site = 0 ;
781+
782+ if (elf_add_reloc_to_insn (file -> elf , sec ,
783+ idx * sizeof (int ),
784+ R_X86_64_PC32 ,
785+ insn -> sec , insn -> offset )) {
786+ WARN ("elf_add_reloc_to_insn: .return_sites" );
787+ return -1 ;
788+ }
789+
790+ idx ++ ;
791+ }
792+
793+ return 0 ;
794+ }
795+
750796static int create_ibt_endbr_seal_sections (struct objtool_file * file )
751797{
752798 struct instruction * insn ;
@@ -1081,6 +1127,11 @@ __weak bool arch_is_retpoline(struct symbol *sym)
10811127 return false;
10821128}
10831129
1130+ __weak bool arch_is_rethunk (struct symbol * sym )
1131+ {
1132+ return false;
1133+ }
1134+
10841135#define NEGATIVE_RELOC ((void *)-1L)
10851136
10861137static struct reloc * insn_reloc (struct objtool_file * file , struct instruction * insn )
@@ -1248,6 +1299,18 @@ static void add_retpoline_call(struct objtool_file *file, struct instruction *in
12481299 annotate_call_site (file , insn , false);
12491300}
12501301
1302+ static void add_return_call (struct objtool_file * file , struct instruction * insn )
1303+ {
1304+ /*
1305+ * Return thunk tail calls are really just returns in disguise,
1306+ * so convert them accordingly.
1307+ */
1308+ insn -> type = INSN_RETURN ;
1309+ insn -> retpoline_safe = true;
1310+
1311+ list_add_tail (& insn -> call_node , & file -> return_thunk_list );
1312+ }
1313+
12511314static bool same_function (struct instruction * insn1 , struct instruction * insn2 )
12521315{
12531316 return insn1 -> func -> pfunc == insn2 -> func -> pfunc ;
@@ -1300,6 +1363,9 @@ static int add_jump_destinations(struct objtool_file *file)
13001363 } else if (reloc -> sym -> retpoline_thunk ) {
13011364 add_retpoline_call (file , insn );
13021365 continue ;
1366+ } else if (reloc -> sym -> return_thunk ) {
1367+ add_return_call (file , insn );
1368+ continue ;
13031369 } else if (insn -> func ) {
13041370 /*
13051371 * External sibling call or internal sibling call with
@@ -2182,6 +2248,9 @@ static int classify_symbols(struct objtool_file *file)
21822248 if (arch_is_retpoline (func ))
21832249 func -> retpoline_thunk = true;
21842250
2251+ if (arch_is_rethunk (func ))
2252+ func -> return_thunk = true;
2253+
21852254 if (!strcmp (func -> name , "__fentry__" ))
21862255 func -> fentry = true;
21872256
@@ -3935,6 +4004,11 @@ int check(struct objtool_file *file)
39354004 if (ret < 0 )
39364005 goto out ;
39374006 warnings += ret ;
4007+
4008+ ret = create_return_sites_sections (file );
4009+ if (ret < 0 )
4010+ goto out ;
4011+ warnings += ret ;
39384012 }
39394013
39404014 if (mcount ) {
0 commit comments