@@ -683,6 +683,52 @@ static int create_static_call_sections(struct objtool_file *file)
683
683
return 0 ;
684
684
}
685
685
686
+ static int create_retpoline_sites_sections (struct objtool_file * file )
687
+ {
688
+ struct instruction * insn ;
689
+ struct section * sec ;
690
+ int idx ;
691
+
692
+ sec = find_section_by_name (file -> elf , ".retpoline_sites" );
693
+ if (sec ) {
694
+ WARN ("file already has .retpoline_sites, skipping" );
695
+ return 0 ;
696
+ }
697
+
698
+ idx = 0 ;
699
+ list_for_each_entry (insn , & file -> retpoline_call_list , call_node )
700
+ idx ++ ;
701
+
702
+ if (!idx )
703
+ return 0 ;
704
+
705
+ sec = elf_create_section (file -> elf , ".retpoline_sites" , 0 ,
706
+ sizeof (int ), idx );
707
+ if (!sec ) {
708
+ WARN ("elf_create_section: .retpoline_sites" );
709
+ return -1 ;
710
+ }
711
+
712
+ idx = 0 ;
713
+ list_for_each_entry (insn , & file -> retpoline_call_list , call_node ) {
714
+
715
+ int * site = (int * )sec -> data -> d_buf + idx ;
716
+ * site = 0 ;
717
+
718
+ if (elf_add_reloc_to_insn (file -> elf , sec ,
719
+ idx * sizeof (int ),
720
+ R_X86_64_PC32 ,
721
+ insn -> sec , insn -> offset )) {
722
+ WARN ("elf_add_reloc_to_insn: .retpoline_sites" );
723
+ return -1 ;
724
+ }
725
+
726
+ idx ++ ;
727
+ }
728
+
729
+ return 0 ;
730
+ }
731
+
686
732
static int create_mcount_loc_sections (struct objtool_file * file )
687
733
{
688
734
struct section * sec ;
@@ -1016,6 +1062,11 @@ static void annotate_call_site(struct objtool_file *file,
1016
1062
return ;
1017
1063
}
1018
1064
1065
+ if (sym -> retpoline_thunk ) {
1066
+ list_add_tail (& insn -> call_node , & file -> retpoline_call_list );
1067
+ return ;
1068
+ }
1069
+
1019
1070
/*
1020
1071
* Many compilers cannot disable KCOV with a function attribute
1021
1072
* so they need a little help, NOP out any KCOV calls from noinstr
@@ -1075,6 +1126,39 @@ static void add_call_dest(struct objtool_file *file, struct instruction *insn,
1075
1126
annotate_call_site (file , insn , sibling );
1076
1127
}
1077
1128
1129
+ static void add_retpoline_call (struct objtool_file * file , struct instruction * insn )
1130
+ {
1131
+ /*
1132
+ * Retpoline calls/jumps are really dynamic calls/jumps in disguise,
1133
+ * so convert them accordingly.
1134
+ */
1135
+ switch (insn -> type ) {
1136
+ case INSN_CALL :
1137
+ insn -> type = INSN_CALL_DYNAMIC ;
1138
+ break ;
1139
+ case INSN_JUMP_UNCONDITIONAL :
1140
+ insn -> type = INSN_JUMP_DYNAMIC ;
1141
+ break ;
1142
+ case INSN_JUMP_CONDITIONAL :
1143
+ insn -> type = INSN_JUMP_DYNAMIC_CONDITIONAL ;
1144
+ break ;
1145
+ default :
1146
+ return ;
1147
+ }
1148
+
1149
+ insn -> retpoline_safe = true;
1150
+
1151
+ /*
1152
+ * Whatever stack impact regular CALLs have, should be undone
1153
+ * by the RETURN of the called function.
1154
+ *
1155
+ * Annotated intra-function calls retain the stack_ops but
1156
+ * are converted to JUMP, see read_intra_function_calls().
1157
+ */
1158
+ remove_insn_ops (insn );
1159
+
1160
+ annotate_call_site (file , insn , false);
1161
+ }
1078
1162
/*
1079
1163
* Find the destination instructions for all jumps.
1080
1164
*/
@@ -1097,19 +1181,7 @@ static int add_jump_destinations(struct objtool_file *file)
1097
1181
dest_sec = reloc -> sym -> sec ;
1098
1182
dest_off = arch_dest_reloc_offset (reloc -> addend );
1099
1183
} else if (reloc -> sym -> retpoline_thunk ) {
1100
- /*
1101
- * Retpoline jumps are really dynamic jumps in
1102
- * disguise, so convert them accordingly.
1103
- */
1104
- if (insn -> type == INSN_JUMP_UNCONDITIONAL )
1105
- insn -> type = INSN_JUMP_DYNAMIC ;
1106
- else
1107
- insn -> type = INSN_JUMP_DYNAMIC_CONDITIONAL ;
1108
-
1109
- list_add_tail (& insn -> call_node ,
1110
- & file -> retpoline_call_list );
1111
-
1112
- insn -> retpoline_safe = true;
1184
+ add_retpoline_call (file , insn );
1113
1185
continue ;
1114
1186
} else if (insn -> func ) {
1115
1187
/* internal or external sibling call (with reloc) */
@@ -1238,18 +1310,7 @@ static int add_call_destinations(struct objtool_file *file)
1238
1310
add_call_dest (file , insn , dest , false);
1239
1311
1240
1312
} else if (reloc -> sym -> retpoline_thunk ) {
1241
- /*
1242
- * Retpoline calls are really dynamic calls in
1243
- * disguise, so convert them accordingly.
1244
- */
1245
- insn -> type = INSN_CALL_DYNAMIC ;
1246
- insn -> retpoline_safe = true;
1247
-
1248
- list_add_tail (& insn -> call_node ,
1249
- & file -> retpoline_call_list );
1250
-
1251
- remove_insn_ops (insn );
1252
- continue ;
1313
+ add_retpoline_call (file , insn );
1253
1314
1254
1315
} else
1255
1316
add_call_dest (file , insn , reloc -> sym , false);
@@ -1980,11 +2041,6 @@ static void mark_rodata(struct objtool_file *file)
1980
2041
file -> rodata = found ;
1981
2042
}
1982
2043
1983
- __weak int arch_rewrite_retpolines (struct objtool_file * file )
1984
- {
1985
- return 0 ;
1986
- }
1987
-
1988
2044
static int decode_sections (struct objtool_file * file )
1989
2045
{
1990
2046
int ret ;
@@ -2057,15 +2113,6 @@ static int decode_sections(struct objtool_file *file)
2057
2113
if (ret )
2058
2114
return ret ;
2059
2115
2060
- /*
2061
- * Must be after add_special_section_alts(), since this will emit
2062
- * alternatives. Must be after add_{jump,call}_destination(), since
2063
- * those create the call insn lists.
2064
- */
2065
- ret = arch_rewrite_retpolines (file );
2066
- if (ret )
2067
- return ret ;
2068
-
2069
2116
return 0 ;
2070
2117
}
2071
2118
@@ -3468,6 +3515,13 @@ int check(struct objtool_file *file)
3468
3515
goto out ;
3469
3516
warnings += ret ;
3470
3517
3518
+ if (retpoline ) {
3519
+ ret = create_retpoline_sites_sections (file );
3520
+ if (ret < 0 )
3521
+ goto out ;
3522
+ warnings += ret ;
3523
+ }
3524
+
3471
3525
if (mcount ) {
3472
3526
ret = create_mcount_loc_sections (file );
3473
3527
if (ret < 0 )
0 commit comments