Можете посмотреть в сторону
fault injection концепции. Она используются как дополнительный шаг в тестировании программы для проверки как ведёт себя код при возникновении ошибок. Минус у всего этого - требуется дополнительная модификация кода (что в вашем случае может быть слишком затратным и избыточным), но существуют вроде и внешние тулзы для модификации кода на лету.
Как другой вариант - написать скрипт для дебагера, который бы при старте программы расставлял брейкпоинты на retq (если надо, чтобы тело функции выполнилось) инструкции и выполнял кастомный ретурн со ошибочным значением.
Пример (gdb):
Файл:
int my_function() {
return 42;
}
int main(void) {
int a = my_function();
printf("%d\n", a);
return 0;
}
Находим адрес ret(q):
(gdb) disassemble my_function
Dump of assembler code for function my_function:
0x08048388 <+0>: push %ebp
0x08048389 <+1>: mov %esp,%ebp
0x0804838b <+3>: mov $0x2a,%eax
0x08048390 <+8>: pop %ebp
0x08048391 <+9>: ret
В файле .gdbinit:
b *0x08048391
commands
return (int)43
continue
end
Запускаем:
(gdb) run
Starting program: /root/a.out
Breakpoint 1, 0x08048391 in foo ()
43 <=== новое значение
[Inferior 1 (process 127) exited normally]