@@ -157,6 +157,12 @@ class LinuxKernelRewriter final : public MetadataRewriter {
157
157
// / Alignment of paravirtual patch structures.
158
158
static constexpr size_t PARA_PATCH_ALIGN = 8 ;
159
159
160
+ // / Section containing Linux bug table.
161
+ ErrorOr<BinarySection &> BugTableSection = std::errc::bad_address;
162
+
163
+ // / Size of bug_entry struct.
164
+ static constexpr size_t BUG_TABLE_ENTRY_SIZE = 12 ;
165
+
160
166
// / Insert an LKMarker for a given code pointer \p PC from a non-code section
161
167
// / \p SectionName.
162
168
void insertLKMarker (uint64_t PC, uint64_t SectionOffset,
@@ -172,9 +178,6 @@ class LinuxKernelRewriter final : public MetadataRewriter {
172
178
// / Process __ksymtab and __ksymtab_gpl.
173
179
void processLKKSymtab (bool IsGPL = false );
174
180
175
- // / Process special linux kernel section, __bug_table.
176
- void processLKBugTable ();
177
-
178
181
// / Process special linux kernel section, .smp_locks.
179
182
void processLKSMPLocks ();
180
183
@@ -200,6 +203,8 @@ class LinuxKernelRewriter final : public MetadataRewriter {
200
203
// / Paravirtual instruction patch sites.
201
204
Error readParaInstructions ();
202
205
206
+ Error readBugTable ();
207
+
203
208
// / Mark instructions referenced by kernel metadata.
204
209
Error markInstructions ();
205
210
@@ -224,6 +229,9 @@ class LinuxKernelRewriter final : public MetadataRewriter {
224
229
if (Error E = readParaInstructions ())
225
230
return E;
226
231
232
+ if (Error E = readBugTable ())
233
+ return E;
234
+
227
235
return Error::success ();
228
236
}
229
237
@@ -289,7 +297,6 @@ void LinuxKernelRewriter::processLKSections() {
289
297
processLKPCIFixup ();
290
298
processLKKSymtab ();
291
299
processLKKSymtab (true );
292
- processLKBugTable ();
293
300
processLKSMPLocks ();
294
301
}
295
302
@@ -356,37 +363,6 @@ void LinuxKernelRewriter::processLKKSymtab(bool IsGPL) {
356
363
}
357
364
}
358
365
359
- // / Process __bug_table section.
360
- // / This section contains information useful for kernel debugging.
361
- // / Each entry in the section is a struct bug_entry that contains a pointer to
362
- // / the ud2 instruction corresponding to the bug, corresponding file name (both
363
- // / pointers use PC relative offset addressing), line number, and flags.
364
- // / The definition of the struct bug_entry can be found in
365
- // / `include/asm-generic/bug.h`
366
- void LinuxKernelRewriter::processLKBugTable () {
367
- ErrorOr<BinarySection &> SectionOrError =
368
- BC.getUniqueSectionByName (" __bug_table" );
369
- if (!SectionOrError)
370
- return ;
371
-
372
- const uint64_t SectionSize = SectionOrError->getSize ();
373
- const uint64_t SectionAddress = SectionOrError->getAddress ();
374
- assert ((SectionSize % 12 ) == 0 &&
375
- " The size of the __bug_table section should be a multiple of 12" );
376
- for (uint64_t I = 0 ; I < SectionSize; I += 12 ) {
377
- const uint64_t EntryAddress = SectionAddress + I;
378
- ErrorOr<uint64_t > Offset = BC.getSignedValueAtAddress (EntryAddress, 4 );
379
- assert (Offset &&
380
- " Reading valid PC-relative offset for a __bug_table entry" );
381
- const int32_t SignedOffset = *Offset;
382
- const uint64_t RefAddress = EntryAddress + SignedOffset;
383
- assert (BC.getBinaryFunctionContainingAddress (RefAddress) &&
384
- " __bug_table entries should point to a function" );
385
-
386
- insertLKMarker (RefAddress, I, SignedOffset, true , " __bug_table" );
387
- }
388
- }
389
-
390
366
// / .smp_locks section contains PC-relative references to instructions with LOCK
391
367
// / prefix. The prefix can be converted to NOP at boot time on non-SMP systems.
392
368
void LinuxKernelRewriter::processLKSMPLocks () {
@@ -1097,6 +1073,65 @@ Error LinuxKernelRewriter::readParaInstructions() {
1097
1073
return Error::success ();
1098
1074
}
1099
1075
1076
+ // / Process __bug_table section.
1077
+ // / This section contains information useful for kernel debugging.
1078
+ // / Each entry in the section is a struct bug_entry that contains a pointer to
1079
+ // / the ud2 instruction corresponding to the bug, corresponding file name (both
1080
+ // / pointers use PC relative offset addressing), line number, and flags.
1081
+ // / The definition of the struct bug_entry can be found in
1082
+ // / `include/asm-generic/bug.h`
1083
+ // /
1084
+ // / NB: find_bug() uses linear search to match an address to an entry in the bug
1085
+ // / table. Hence there is no need to sort entries when rewriting the table.
1086
+ Error LinuxKernelRewriter::readBugTable () {
1087
+ BugTableSection = BC.getUniqueSectionByName (" __bug_table" );
1088
+ if (!BugTableSection)
1089
+ return Error::success ();
1090
+
1091
+ if (BugTableSection->getSize () % BUG_TABLE_ENTRY_SIZE)
1092
+ return createStringError (errc::executable_format_error,
1093
+ " bug table size error" );
1094
+
1095
+ const uint64_t SectionAddress = BugTableSection->getAddress ();
1096
+ DataExtractor DE (BugTableSection->getContents (), BC.AsmInfo ->isLittleEndian (),
1097
+ BC.AsmInfo ->getCodePointerSize ());
1098
+ DataExtractor::Cursor Cursor (0 );
1099
+ uint32_t EntryID = 0 ;
1100
+ while (Cursor && Cursor.tell () < BugTableSection->getSize ()) {
1101
+ const uint64_t Pos = Cursor.tell ();
1102
+ const uint64_t InstAddress =
1103
+ SectionAddress + Pos + (int32_t )DE.getU32 (Cursor);
1104
+ Cursor.seek (Pos + BUG_TABLE_ENTRY_SIZE);
1105
+
1106
+ if (!Cursor)
1107
+ return createStringError (errc::executable_format_error,
1108
+ " out of bounds while reading __bug_table" );
1109
+
1110
+ ++EntryID;
1111
+
1112
+ BinaryFunction *BF = BC.getBinaryFunctionContainingAddress (InstAddress);
1113
+ if (!BF && opts::Verbosity) {
1114
+ BC.outs () << " BOLT-INFO: no function matches address 0x"
1115
+ << Twine::utohexstr (InstAddress)
1116
+ << " referenced by bug table\n " ;
1117
+ }
1118
+
1119
+ if (BF && BC.shouldEmit (*BF)) {
1120
+ MCInst *Inst = BF->getInstructionAtOffset (InstAddress - BF->getAddress ());
1121
+ if (!Inst)
1122
+ return createStringError (errc::executable_format_error,
1123
+ " no instruction at address 0x%" PRIx64
1124
+ " referenced by bug table entry %d" ,
1125
+ InstAddress, EntryID);
1126
+ BC.MIB ->addAnnotation (*Inst, " BugEntry" , EntryID);
1127
+ }
1128
+ }
1129
+
1130
+ BC.outs () << " BOLT-INFO: parsed " << EntryID << " bug table entries\n " ;
1131
+
1132
+ return Error::success ();
1133
+ }
1134
+
1100
1135
} // namespace
1101
1136
1102
1137
std::unique_ptr<MetadataRewriter>
0 commit comments