Скомпилировать coreutils в защищённом режиме несложно:
./configure CFLAGS='-Wno-error=suggest-attribute=const -m128 -Wno-error=suggest-attribute=pure -Wno-error=suggest-attribute=noreturn -Wno-error=suggest-attribute=format -Wno-error=suggest-attribute=cold -Wno-error=suggest-attribute=malloc -Wno-error=bad-macro-redef -Wno-error=type-limits -Wno-error=shadow=global' LDFLAGS='-m128'
Изначально не проходит достаточно много тестов:
FAIL: tests/misc/help-version.sh
FAIL: tests/pr/pr-tests.pl
FAIL: tests/misc/date-debug.sh
FAIL: tests/misc/sort.pl
FAIL: tests/misc/sort-discrim.sh
FAIL: tests/misc/sort-month.sh
FAIL: tests/misc/sort-rand.sh
FAIL: tests/misc/yes.sh
FAIL: tests/du/long-from-unreadable.sh
FAIL: tests/rmdir/symlink-errors.sh
В тесте help-version.sh на самом деле вся проблема в программе shuf - она попросту не запускается.
Проблема - в создании неинициализированного блока памяти в lib/randread.c
static struct randread_source *
simple_new (FILE *source, void const *handler_arg)
{
struct randread_source *s = xmalloc (sizeof *s);
s->source = source;
s->handler = randread_error;
s->handler_arg = handler_arg;
return s;
}
(дальше s->buf используется в lib/rand-isaac.c, ISAAC_MIX как переменная seed):
/* The basic ISAAC initialization pass. */
#define ISAAC_MIX(s, a, b, c, d, e, f, g, h, seed) \
{ \
int i; \
\
for (i = 0; i < ISAAC_WORDS; i += 8) \
{ \
a += seed[i]; \
b += seed[i + 1]; \
c += seed[i + 2]; \
d += seed[i + 3]; \
e += seed[i + 4]; \
f += seed[i + 5]; \
g += seed[i + 6]; \
h += seed[i + 7]; \
mix (a, b, c, d, e, f, g, h); \
s->m[i] = a; \
s->m[i + 1] = b; \
s->m[i + 2] = c; \
s->m[i + 3] = d; \
s->m[i + 4] = e; \
s->m[i + 5] = f; \
s->m[i + 6] = g; \
s->m[i + 7] = h; \
} \
}
Решение очевидно и корректно - очищаем память после создания.
static struct randread_source *
simple_new (FILE *source, void const *handler_arg)
{
struct randread_source *s = xmalloc (sizeof *s);
memset(s, 0, sizeof *s);
s->source = source;
s->handler = randread_error;
s->handler_arg = handler_arg;
return s;
}
Программа shuf теперь работает. Новый список невыполненных тестов стал существенно короче:
FAIL: tests/pr/pr-tests.pl
FAIL: tests/misc/date-debug.sh
FAIL: tests/misc/tac.pl
FAIL: tests/misc/yes.sh
FAIL: tests/du/long-from-unreadable.sh
FAIL: tests/rmdir/symlink-errors.sh
Следующей исправим программу уes
Она полагается на весьма вольное допущение о том, что элементы, переданные в argv, следуют одним блоком памяти, один за другим (хотя на самом деле это массив указателей на указатели и не более того). Но проверяют это в строчках
do
{
size_t operand_len = strlen (*operandp);
bufalloc += operand_len + 1;
if (operandp + 1 < operand_lim
&& *operandp + operand_len + 1 != operandp[1])
reuse_operand_strings = false;
}
while (++operandp < operand_lim);
Тут (в обычном режиме), если указатели расположены не единым блоком, то данная оптимизация отключается. В защищённом режиме это всё не работает, потому что за границы указателя выходить нельзя ни при каких условиях.
Добавляем специальный код для защищённого режима E2K
#ifdef __e2k__
if (sizeof(void*) == 16)
{ // in protected mode, pointers are 128-bit
reuse_operand_strings = false;
}
#endif
Новый список невыполненных тестов:
FAIL: tests/pr/pr-tests.pl
FAIL: tests/misc/date-debug.sh
FAIL: tests/misc/tac.pl
FAIL: tests/misc/tac-2-nonseekable.sh
FAIL: tests/du/long-from-unreadable.sh
FAIL: tests/rmdir/symlink-errors.sh
Теперь появился новый сбойнувший тест tac, который, видимо, зависел от работы yes.