@@ -212,6 +212,11 @@ class LinuxKernelRewriter final : public MetadataRewriter {
212
212
// / Size of bug_entry struct.
213
213
static constexpr size_t BUG_TABLE_ENTRY_SIZE = 12 ;
214
214
215
+ // / List of bug entries per function.
216
+ using FunctionBugListType =
217
+ DenseMap<BinaryFunction *, SmallVector<uint32_t , 2 >>;
218
+ FunctionBugListType FunctionBugList;
219
+
215
220
// / .pci_fixup section.
216
221
ErrorOr<BinarySection &> PCIFixupSection = std::errc::bad_address;
217
222
static constexpr size_t PCI_FIXUP_ENTRY_SIZE = 16 ;
@@ -254,7 +259,9 @@ class LinuxKernelRewriter final : public MetadataRewriter {
254
259
Error readParaInstructions ();
255
260
Error rewriteParaInstructions ();
256
261
262
+ // / __bug_table section handling.
257
263
Error readBugTable ();
264
+ Error rewriteBugTable ();
258
265
259
266
// / Do no process functions containing instruction annotated with
260
267
// / \p Annotation.
@@ -339,6 +346,9 @@ class LinuxKernelRewriter final : public MetadataRewriter {
339
346
if (Error E = rewriteStaticKeysJumpTable ())
340
347
return E;
341
348
349
+ if (Error E = rewriteBugTable ())
350
+ return E;
351
+
342
352
return Error::success ();
343
353
}
344
354
@@ -1164,15 +1174,17 @@ Error LinuxKernelRewriter::rewriteParaInstructions() {
1164
1174
}
1165
1175
1166
1176
// / Process __bug_table section.
1167
- // / This section contains information useful for kernel debugging.
1177
+ // / This section contains information useful for kernel debugging, mostly
1178
+ // / utilized by WARN()/WARN_ON() macros and deprecated BUG()/BUG_ON().
1179
+ // /
1168
1180
// / Each entry in the section is a struct bug_entry that contains a pointer to
1169
1181
// / the ud2 instruction corresponding to the bug, corresponding file name (both
1170
1182
// / pointers use PC relative offset addressing), line number, and flags.
1171
1183
// / The definition of the struct bug_entry can be found in
1172
- // / `include/asm-generic/bug.h`
1173
- // /
1174
- // / NB: find_bug() uses linear search to match an address to an entry in the bug
1175
- // / table. Hence there is no need to sort entries when rewriting the table .
1184
+ // / `include/asm-generic/bug.h`. The first entry in the struct is an instruction
1185
+ // / address encoded as a PC-relative offset. In theory, it could be an absolute
1186
+ // / address if CONFIG_GENERIC_BUG_RELATIVE_POINTERS is not set, but in practice
1187
+ // / the kernel code relies on it being a relative offset on x86-64 .
1176
1188
Error LinuxKernelRewriter::readBugTable () {
1177
1189
BugTableSection = BC.getUniqueSectionByName (" __bug_table" );
1178
1190
if (!BugTableSection)
@@ -1215,6 +1227,8 @@ Error LinuxKernelRewriter::readBugTable() {
1215
1227
" referenced by bug table entry %d" ,
1216
1228
InstAddress, EntryID);
1217
1229
BC.MIB ->addAnnotation (*Inst, " BugEntry" , EntryID);
1230
+
1231
+ FunctionBugList[BF].push_back (EntryID);
1218
1232
}
1219
1233
}
1220
1234
@@ -1223,6 +1237,52 @@ Error LinuxKernelRewriter::readBugTable() {
1223
1237
return Error::success ();
1224
1238
}
1225
1239
1240
+ // / find_bug() uses linear search to match an address to an entry in the bug
1241
+ // / table. Hence, there is no need to sort entries when rewriting the table.
1242
+ // / When we need to erase an entry, we set its instruction address to zero.
1243
+ Error LinuxKernelRewriter::rewriteBugTable () {
1244
+ if (!BugTableSection)
1245
+ return Error::success ();
1246
+
1247
+ for (BinaryFunction &BF : llvm::make_second_range (BC.getBinaryFunctions ())) {
1248
+ if (!BC.shouldEmit (BF))
1249
+ continue ;
1250
+
1251
+ if (!FunctionBugList.count (&BF))
1252
+ continue ;
1253
+
1254
+ // Bugs that will be emitted for this function.
1255
+ DenseSet<uint32_t > EmittedIDs;
1256
+ for (BinaryBasicBlock &BB : BF) {
1257
+ for (MCInst &Inst : BB) {
1258
+ if (!BC.MIB ->hasAnnotation (Inst, " BugEntry" ))
1259
+ continue ;
1260
+ const uint32_t ID = BC.MIB ->getAnnotationAs <uint32_t >(Inst, " BugEntry" );
1261
+ EmittedIDs.insert (ID);
1262
+
1263
+ // Create a relocation entry for this bug entry.
1264
+ MCSymbol *Label =
1265
+ BC.MIB ->getOrCreateInstLabel (Inst, " __BUG_" , BC.Ctx .get ());
1266
+ const uint64_t EntryOffset = (ID - 1 ) * BUG_TABLE_ENTRY_SIZE;
1267
+ BugTableSection->addRelocation (EntryOffset, Label, ELF::R_X86_64_PC32,
1268
+ /* Addend*/ 0 );
1269
+ }
1270
+ }
1271
+
1272
+ // Clear bug entries that were not emitted for this function, e.g. as a
1273
+ // result of DCE, but setting their instruction address to zero.
1274
+ for (const uint32_t ID : FunctionBugList[&BF]) {
1275
+ if (!EmittedIDs.count (ID)) {
1276
+ const uint64_t EntryOffset = (ID - 1 ) * BUG_TABLE_ENTRY_SIZE;
1277
+ BugTableSection->addRelocation (EntryOffset, nullptr , ELF::R_X86_64_PC32,
1278
+ /* Addend*/ 0 );
1279
+ }
1280
+ }
1281
+ }
1282
+
1283
+ return Error::success ();
1284
+ }
1285
+
1226
1286
// / The kernel can replace certain instruction sequences depending on hardware
1227
1287
// / it is running on and features specified during boot time. The information
1228
1288
// / about alternative instruction sequences is stored in .altinstructions
0 commit comments