@@ -749,6 +749,52 @@ static int create_retpoline_sites_sections(struct objtool_file *file)
749749 return 0 ;
750750}
751751
752+ static int create_return_sites_sections (struct objtool_file * file )
753+ {
754+ struct instruction * insn ;
755+ struct section * sec ;
756+ int idx ;
757+
758+ sec = find_section_by_name (file -> elf , ".return_sites" );
759+ if (sec ) {
760+ WARN ("file already has .return_sites, skipping" );
761+ return 0 ;
762+ }
763+
764+ idx = 0 ;
765+ list_for_each_entry (insn , & file -> return_thunk_list , call_node )
766+ idx ++ ;
767+
768+ if (!idx )
769+ return 0 ;
770+
771+ sec = elf_create_section (file -> elf , ".return_sites" , 0 ,
772+ sizeof (int ), idx );
773+ if (!sec ) {
774+ WARN ("elf_create_section: .return_sites" );
775+ return -1 ;
776+ }
777+
778+ idx = 0 ;
779+ list_for_each_entry (insn , & file -> return_thunk_list , call_node ) {
780+
781+ int * site = (int * )sec -> data -> d_buf + idx ;
782+ * site = 0 ;
783+
784+ if (elf_add_reloc_to_insn (file -> elf , sec ,
785+ idx * sizeof (int ),
786+ R_X86_64_PC32 ,
787+ insn -> sec , insn -> offset )) {
788+ WARN ("elf_add_reloc_to_insn: .return_sites" );
789+ return -1 ;
790+ }
791+
792+ idx ++ ;
793+ }
794+
795+ return 0 ;
796+ }
797+
752798static int create_ibt_endbr_seal_sections (struct objtool_file * file )
753799{
754800 struct instruction * insn ;
@@ -1083,6 +1129,11 @@ __weak bool arch_is_retpoline(struct symbol *sym)
10831129 return false;
10841130}
10851131
1132+ __weak bool arch_is_rethunk (struct symbol * sym )
1133+ {
1134+ return false;
1135+ }
1136+
10861137#define NEGATIVE_RELOC ((void *)-1L)
10871138
10881139static struct reloc * insn_reloc (struct objtool_file * file , struct instruction * insn )
@@ -1250,6 +1301,18 @@ static void add_retpoline_call(struct objtool_file *file, struct instruction *in
12501301 annotate_call_site (file , insn , false);
12511302}
12521303
1304+ static void add_return_call (struct objtool_file * file , struct instruction * insn )
1305+ {
1306+ /*
1307+ * Return thunk tail calls are really just returns in disguise,
1308+ * so convert them accordingly.
1309+ */
1310+ insn -> type = INSN_RETURN ;
1311+ insn -> retpoline_safe = true;
1312+
1313+ list_add_tail (& insn -> call_node , & file -> return_thunk_list );
1314+ }
1315+
12531316static bool same_function (struct instruction * insn1 , struct instruction * insn2 )
12541317{
12551318 return insn1 -> func -> pfunc == insn2 -> func -> pfunc ;
@@ -1302,6 +1365,9 @@ static int add_jump_destinations(struct objtool_file *file)
13021365 } else if (reloc -> sym -> retpoline_thunk ) {
13031366 add_retpoline_call (file , insn );
13041367 continue ;
1368+ } else if (reloc -> sym -> return_thunk ) {
1369+ add_return_call (file , insn );
1370+ continue ;
13051371 } else if (insn -> func ) {
13061372 /*
13071373 * External sibling call or internal sibling call with
@@ -2184,6 +2250,9 @@ static int classify_symbols(struct objtool_file *file)
21842250 if (arch_is_retpoline (func ))
21852251 func -> retpoline_thunk = true;
21862252
2253+ if (arch_is_rethunk (func ))
2254+ func -> return_thunk = true;
2255+
21872256 if (!strcmp (func -> name , "__fentry__" ))
21882257 func -> fentry = true;
21892258
@@ -3972,6 +4041,11 @@ int check(struct objtool_file *file)
39724041 if (ret < 0 )
39734042 goto out ;
39744043 warnings += ret ;
4044+
4045+ ret = create_return_sites_sections (file );
4046+ if (ret < 0 )
4047+ goto out ;
4048+ warnings += ret ;
39754049 }
39764050
39774051 if (opts .mcount ) {
0 commit comments