.got.plt
необходим для выполнения вызовов библиотеки (, включая, помимо прочего, вызовыlibc
). После того, как вы закончите повреждение этого раздела, любые вызовы libc будут недоступны -.
Если вы запускаете двоичный файл через gdb
, вы не должны получить ошибку сегментации в scanf
— вы должны получить ошибку сегментации в printf@plt
, так как динамический вызов не может быть выполнен с поврежденным .got.plt
раздел.
Вы по-прежнему сможете выполнять не -динамические и системные вызовы:
#include <stdio.h>
__asm(
"finish:"
"mov $60, %rax\n"
"mov $42, %rdi\n"
"syscall\n"
);
int gv=10;
int main(){
char *v=(char*)0x601000;//0x601030
printf("gv=%p\n", &gv);
scanf("%s", v);
_Noreturn void finish(void);
finish();
//should exit with 42
printf("You gave=%s\n", v);
}
Для этого вам нужно разбить каждую строку входного файла на белый -пробел (, что является xargs
поведением по умолчанию ), а затем получить xargs
для запуска sh
script один раз для каждого слова, используя -n 1
. В качестве альтернативы вы можете заставить сценарий оболочки перебирать "$@".
Вы не можете использовать здесь -I {}
, потому что это заставляет xargs
читать входной файл по одной строке за раз. Даже если вы установите разделитель на пробел с помощью -d ' '
, вы получите ошибки в конце каждой строки ввода, когда он начнет читать следующую строку ввода.
К счастью, вам вообще не нужно использовать -I {}
-вы уже просто добавляете эхо-слово ввода в конец командной строки sh
в качестве отдельного аргумента, то есть xargs
' поведение по умолчанию без -I.
В сценарии оболочки вы ссылаетесь на аргумент по его позиционному параметру (, т.е. как $1
), как и в любом сценарии оболочки. Вы можете использовать $1
столько раз, сколько хотите в сценарии оболочки.
Вам также необходимо предоставить аргумент 0 (произвольное имя для процесса sh -строка "sh" удобна -но вы можете использовать любое имя, если хотите, чтобы его было легко найти вps
)для команды sh -c '...script...'
. Он должен быть первым аргументом после аргумента '...script...'
и будет $0
внутри сценария оболочки.
Итак,вам нужно сделать что-то вроде этого (без цикла for):
xargs -n 1 sh -c \
'./hisat2-2.1.0/hisat2 -p 8 --dta -x./indexes/chrX_tran \
-1 "./samples/$1_chrX_1.fastq.gz" -2 "./samples/$1_chrX_2.fastq.gz" \
-S "./map/$1_chrX.sam"' sh <./samples.txt
или (с циклом for):
xargs sh -c '
for f in "$@"; do \
./hisat2-2.1.0/hisat2 -p 8 --dta -x./indexes/chrX_tran \
-1 "./samples/${f}_chrX_1.fastq.gz" -2 "./samples/${f}_chrX_2.fastq.gz" \
-S "./map/${f}_chrX.sam"
done' sh <./samples.txt
Версия с циклом for будет быстрее, потому что ей не нужно выполнять sh
несколько раз (один раз для каждого "слова" ).
Он запускается sh
как можно меньше раз, при этом пределом является максимальная длина строки команды -оболочки (около 2 МБ в современных системах ). Если samples.txt
не является чрезвычайно большим (более 200 000 записей ), это означает, что он будет запущен sh
только один раз.
xargs не нужен для такой работы. Следующее будет работать в bash и, возможно, в других оболочках, подобных Bourne -, которые поддерживают массивы и параметр -a
для read
.
while read -a words; do
for f in "${words[@]}"; do
./hisat2-2.1.0/hisat2 -p 8 --dta -x./indexes/chrX_tran \
-1 "./samples/${f}_chrX_1.fastq.gz" \
-2 "./samples/${f}_chrX_2.fastq.gz" \
-S "./map/${f}_chrX.sam"
done
done < samples.txt
Это считывает каждое слово каждой входной строки в массив bash, затем (с помощью цикла for
, перебирающего каждое слово в массиве ), запускает программу hisat2 с соответствующими аргументами.
Тем не менее, см.:Почему использование цикла оболочки для обработки текста считается плохой практикой?
awk '{
for (i=1;i<=NF;i++) {
printf "./hisat2-2.1.0/hisat2 -p 8 --dta -x./indexes/chrX_tran -1 \"./samples/%s_chrX_1.fastq.gz\" -2 \"./samples/%s_chrX_2.fastq.gz\" -S \"./map/%s_chrX.sam\"\n", $i, $i,$i;
}
}'./samples.txt | sh
Обратите внимание, что это направляет вывод awk в sh для выполнения. Без этой трубы в sh вывод выглядит как:
./hisat2-2.1.0/hisat2 -p 8 --dta -x./indexes/chrX_tran -1 "./samples/ERR199044_chrX_1.fastq.gz" -2 "./samples/ERR199044_chrX_2.fastq.gz" -S "./map/ERR199044_chrX.sam"
./hisat2-2.1.0/hisat2 -p 8 --dta -x./indexes/chrX_tran -1 "./samples/ERR188104_chrX_1.fastq.gz" -2 "./samples/ERR188104_chrX_2.fastq.gz" -S "./map/ERR188104_chrX.sam"
./hisat2-2.1.0/hisat2 -p 8 --dta -x./indexes/chrX_tran -1 "./samples/ERR188234_chrX_1.fastq.gz" -2 "./samples/ERR188234_chrX_2.fastq.gz" -S "./map/ERR188234_chrX.sam"
./hisat2-2.1.0/hisat2 -p 8 --dta -x./indexes/chrX_tran -1 "./samples/ERR188245_chrX_1.fastq.gz" -2 "./samples/ERR188245_chrX_2.fastq.gz" -S "./map/ERR188245_chrX.sam"
Это также будет выполняться быстро, так как сценарий sh выполняет каждую строку по мере ее вывода сценарием awk.
В качестве альтернативы вы можете использовать sprintf
, чтобы поместить командную строку в переменную, а не printf
в стандартный вывод. Затем вы можете использовать функцию awk
system()
для ее непосредственного выполнения, аналогично приведенному ниже примеру perl:
perl -lane '
foreach $f (@F) {
system(qw(./hisat2-2.1.0/hisat2 -p 8 --dta -x./indexes/chrX_tran),
-1, "./samples/${f}_chrX_1.fastq.gz",
-2, "./samples/${f}_chrX_2.fastq.gz",
"-S", "./map/${f}_chrX.sam");
};'./samples.txt
Здесь используется функция perl
system()
, поэтому команды выполняются напрямую, без необходимости передачи в sh
.
Для тестового запуска -добавьте слово echo
и пробел сразу после оператора qw(
кавычки -.
Кстати,было бы проще добавить код, чтобы проверить, существуют ли файлы, и/или проверить, был ли каждый запуск ./hisat2-2.1.0/hisat2
успешным, или пост -обработать вывод в этой версии perl, чем в версиях оболочки или awk -, особенно если бы он был написан отдельным -шрифтом, а не одним -вкладышем. Например:
#!/usr/bin/perl -w
use strict;
while(<>) {
foreach my $f (split) {
my $f1 = "./samples/${f}_chrX_1.fastq.gz";
my $f2 = "./samples/${f}_chrX_2.fastq.gz";
my $sam = "./map/${f}_chrX.sam";
if (!(-r $f1 && -r $f2 && -r $sam)) {
warn "Missing or unreadable file for $f\n";
next
};
my $rc = system(
qw(echo./hisat2-2.1.0/hisat2 -p 8 --dta -x./indexes/chrX_tran),
-1, $f1, -2, $f2, '-S', $sam
);
if ($rc) {
warn "hisat2 returned non-zero exit code for $f: $rc\n";
};
}
}