@@ -36,6 +36,10 @@ static cl::opt<bool>
36
36
DumpORC (" dump-orc" , cl::desc(" dump raw ORC unwind information (sorted)" ),
37
37
cl::init(false ), cl::Hidden, cl::cat(BoltCategory));
38
38
39
+ static cl::opt<bool > DumpParavirtualPatchSites (
40
+ " dump-para-sites" , cl::desc(" dump Linux kernel paravitual patch sites" ),
41
+ cl::init(false ), cl::Hidden, cl::cat(BoltCategory));
42
+
39
43
static cl::opt<bool > DumpStaticCalls (" dump-static-calls" ,
40
44
cl::desc (" dump Linux kernel static calls" ),
41
45
cl::init(false ), cl::Hidden,
@@ -147,6 +151,12 @@ class LinuxKernelRewriter final : public MetadataRewriter {
147
151
// / Functions with exception handling code.
148
152
DenseSet<BinaryFunction *> FunctionsWithExceptions;
149
153
154
+ // / Section with paravirtual patch sites.
155
+ ErrorOr<BinarySection &> ParavirtualPatchSection = std::errc::bad_address;
156
+
157
+ // / Alignment of paravirtual patch structures.
158
+ static constexpr size_t PARA_PATCH_ALIGN = 8 ;
159
+
150
160
// / Insert an LKMarker for a given code pointer \p PC from a non-code section
151
161
// / \p SectionName.
152
162
void insertLKMarker (uint64_t PC, uint64_t SectionOffset,
@@ -187,6 +197,9 @@ class LinuxKernelRewriter final : public MetadataRewriter {
187
197
Error readExceptionTable ();
188
198
Error rewriteExceptionTable ();
189
199
200
+ // / Paravirtual instruction patch sites.
201
+ Error readParaInstructions ();
202
+
190
203
// / Mark instructions referenced by kernel metadata.
191
204
Error markInstructions ();
192
205
@@ -208,6 +221,9 @@ class LinuxKernelRewriter final : public MetadataRewriter {
208
221
if (Error E = readExceptionTable ())
209
222
return E;
210
223
224
+ if (Error E = readParaInstructions ())
225
+ return E;
226
+
211
227
return Error::success ();
212
228
}
213
229
@@ -1013,6 +1029,74 @@ Error LinuxKernelRewriter::rewriteExceptionTable() {
1013
1029
return Error::success ();
1014
1030
}
1015
1031
1032
+ // / .parainsrtuctions section contains information for patching parvirtual call
1033
+ // / instructions during runtime. The entries in the section are in the form:
1034
+ // /
1035
+ // / struct paravirt_patch_site {
1036
+ // / u8 *instr; /* original instructions */
1037
+ // / u8 type; /* type of this instruction */
1038
+ // / u8 len; /* length of original instruction */
1039
+ // / };
1040
+ // /
1041
+ // / Note that the structures are aligned at 8-byte boundary.
1042
+ Error LinuxKernelRewriter::readParaInstructions () {
1043
+ ParavirtualPatchSection = BC.getUniqueSectionByName (" .parainstructions" );
1044
+ if (!ParavirtualPatchSection)
1045
+ return Error::success ();
1046
+
1047
+ DataExtractor DE = DataExtractor (ParavirtualPatchSection->getContents (),
1048
+ BC.AsmInfo ->isLittleEndian (),
1049
+ BC.AsmInfo ->getCodePointerSize ());
1050
+ uint32_t EntryID = 0 ;
1051
+ DataExtractor::Cursor Cursor (0 );
1052
+ while (Cursor && !DE.eof (Cursor)) {
1053
+ const uint64_t NextOffset = alignTo (Cursor.tell (), Align (PARA_PATCH_ALIGN));
1054
+ if (!DE.isValidOffset (NextOffset))
1055
+ break ;
1056
+
1057
+ Cursor.seek (NextOffset);
1058
+
1059
+ const uint64_t InstrLocation = DE.getU64 (Cursor);
1060
+ const uint8_t Type = DE.getU8 (Cursor);
1061
+ const uint8_t Len = DE.getU8 (Cursor);
1062
+
1063
+ if (!Cursor)
1064
+ return createStringError (errc::executable_format_error,
1065
+ " out of bounds while reading .parainstructions" );
1066
+
1067
+ ++EntryID;
1068
+
1069
+ if (opts::DumpParavirtualPatchSites) {
1070
+ BC.outs () << " Paravirtual patch site: " << EntryID << ' \n ' ;
1071
+ BC.outs () << " \t Instr: 0x" << Twine::utohexstr (InstrLocation)
1072
+ << " \n\t Type: 0x" << Twine::utohexstr (Type) << " \n\t Len: 0x"
1073
+ << Twine::utohexstr (Len) << ' \n ' ;
1074
+ }
1075
+
1076
+ BinaryFunction *BF = BC.getBinaryFunctionContainingAddress (InstrLocation);
1077
+ if (!BF && opts::Verbosity) {
1078
+ BC.outs () << " BOLT-INFO: no function matches address 0x"
1079
+ << Twine::utohexstr (InstrLocation)
1080
+ << " referenced by paravirutal patch site\n " ;
1081
+ }
1082
+
1083
+ if (BF && BC.shouldEmit (*BF)) {
1084
+ MCInst *Inst =
1085
+ BF->getInstructionAtOffset (InstrLocation - BF->getAddress ());
1086
+ if (!Inst)
1087
+ return createStringError (errc::executable_format_error,
1088
+ " no instruction at address 0x%" PRIx64
1089
+ " in paravirtual call site %d" ,
1090
+ InstrLocation, EntryID);
1091
+ BC.MIB ->addAnnotation (*Inst, " ParaSite" , EntryID);
1092
+ }
1093
+ }
1094
+
1095
+ BC.outs () << " BOLT-INFO: parsed " << EntryID << " paravirtual patch sites\n " ;
1096
+
1097
+ return Error::success ();
1098
+ }
1099
+
1016
1100
} // namespace
1017
1101
1018
1102
std::unique_ptr<MetadataRewriter>
0 commit comments