Alexander Monakov
2018-11-23 14:06:38 UTC
Hi,
short, objtool was complaining about unreachable code. To be fair though,
gcc could have made the problem easier to spot.
Now for the details.
The repro uses an unusual (randomized) kernel config, in particular gcov is
enabled and NR_CPUS is 1. Thus we have
static int duplicate_processor_ids[] = {
[0 ... 1 - 1] = -1,
};
and the compiler deduces that the loop in acpi_duplicate_processor_id does not
iterate:
bool acpi_duplicate_processor_id(int proc_id)
{
int i;
for (i = 0; i < nr_duplicate_ids; i++) {
if (duplicate_processor_ids[i] == proc_id)
return true;
}
return false;
}
However as gcov is enabled, loop backedge remains, followed by gcov counter
increment and __builtin_unreachable() (on GIMPLE). On RTL, however, the basic
block with the increment ends with a barrier rtx, which is not visible in
assembly and looks just as if control flow falls through to a function exit.
Since the exit in question corresponds to a shrink-wrapped early exit that
does not push/pop registers, objtool complains.
Ultimately this is poor luck, if gcc optimized the code better or terminated
the block that-should-not-be-reached with ud2, it would not arise.
Alexander
Hello everyone!
some attention of gcc developers.
https://www.openwall.com/lists/kernel-hardening/2018/11/14/1
So just for information, it isn't a plugin bug. I'll elaborate below, but insome attention of gcc developers.
https://www.openwall.com/lists/kernel-hardening/2018/11/14/1
short, objtool was complaining about unreachable code. To be fair though,
gcc could have made the problem easier to spot.
Now for the details.
The repro uses an unusual (randomized) kernel config, in particular gcov is
enabled and NR_CPUS is 1. Thus we have
static int duplicate_processor_ids[] = {
[0 ... 1 - 1] = -1,
};
and the compiler deduces that the loop in acpi_duplicate_processor_id does not
iterate:
bool acpi_duplicate_processor_id(int proc_id)
{
int i;
for (i = 0; i < nr_duplicate_ids; i++) {
if (duplicate_processor_ids[i] == proc_id)
return true;
}
return false;
}
However as gcov is enabled, loop backedge remains, followed by gcov counter
increment and __builtin_unreachable() (on GIMPLE). On RTL, however, the basic
block with the increment ends with a barrier rtx, which is not visible in
assembly and looks just as if control flow falls through to a function exit.
Since the exit in question corresponds to a shrink-wrapped early exit that
does not push/pop registers, objtool complains.
Ultimately this is poor luck, if gcc optimized the code better or terminated
the block that-should-not-be-reached with ud2, it would not arise.
Alexander