На самом деле это четыре вопроса:
OP упоминает xterm, но только последние два, возможно, относятся к xterm.
Для (1) и (2) команда echo не очень помогает. Лучше использовать printf
, который распознает экранирование обратной косой черты. В некоторых реализациях (например, GNU coreutils ), который включает константы Unicode, например,
printf '\u94f6\btest'
, хотя для регулярных выражений вам снова лучше использовать язык сценариев, такой как Perl (который может обрабатывать UTF-8).
Дополнительная литература:
Вопросы (3) и (4) более интересны. Во-первых, сценарий не может точно сказать, сколько символьных ячеек занимает строка, а может измерить это только постфактум. Это потому, что ширина основана на сочетании поведения терминала и ядра.
wcwidth
; вас предупреждают, что он может быть неполным и не соответствовать фактической информации о языковом стандарте системы. wcwidth
. Системы на базе Linux, начиная с 2004 , имеют функцию в stty
под названием iutf8
: , которая сообщает ядру , что входные данные кодируются в UTF -8, для правильной поддержки редактирования в каноническом режиме ввода
Вы можете , как предлагается, использовать отчет о позиции курсора (escape-последовательность), чтобы найти положение курсора в разных точках. Но если вы собираетесь использовать это, чтобы решить, как очистить строку, может показаться более прямым просто переместить в позицию перед печатью значения Unicode и начать очистку с этой точки.
В качестве альтернативы вы можете указать терминалу сохранить позицию курсора перед печатью широкого символа и восстановить ее (вернуться). Это может показаться более понятным и предсказуемым. После восстановления позиции курсора вы можете очистить строку. Все три могут быть выполнены с помощью управляющих последовательностей - или tput
:
tput sc
printf '\u94f6'
tput rc
tput el
printf 'test'
Помимо демонстрации, это имеет недостаток, заключающийся в том, что терминал будет иметь только одну сохраненную позицию для курсора, и это для обеспечения очищая символ одинарной / двойной ширины, очищается вся строка. Но курсор окажется в «нужном» месте.
В выводе gdb
отсутствует важная часть информации :о правах доступа к страницам. (Они показаны в Solaris и FreeBSD , но не в Linux. )Вы можете увидеть их, взглянув на /proc/<pid>/maps
; карты для вашего примера Protostar показывают
$ cat /proc/.../maps
08048000-08049000 r-xp 00000000 00:0f 2925 /opt/protostar/bin/stack6
08049000-0804a000 rwxp 00000000 00:0f 2925 /opt/protostar/bin/stack6
b7e96000-b7e97000 rwxp 00000000 00:00 0
b7e97000-b7fd5000 r-xp 00000000 00:0f 759 /lib/libc-2.11.2.so
b7fd5000-b7fd6000 ---p 0013e000 00:0f 759 /lib/libc-2.11.2.so
b7fd6000-b7fd8000 r-xp 0013e000 00:0f 759 /lib/libc-2.11.2.so
b7fd8000-b7fd9000 rwxp 00140000 00:0f 759 /lib/libc-2.11.2.so
b7fd9000-b7fdc000 rwxp 00000000 00:00 0
b7fe0000-b7fe2000 rwxp 00000000 00:00 0
b7fe2000-b7fe3000 r-xp 00000000 00:00 0 [vdso]
b7fe3000-b7ffe000 r-xp 00000000 00:0f 741 /lib/ld-2.11.2.so
b7ffe000-b7fff000 r-xp 0001a000 00:0f 741 /lib/ld-2.11.2.so
b7fff000-b8000000 rwxp 0001b000 00:0f 741 /lib/ld-2.11.2.so
bffeb000-c0000000 rwxp 00000000 00:0f 0 [stack]
(Пример Protostar работает на виртуальной машине, которую легко взломать, предположительно, чтобы сделать упражнения более понятными :здесь нет защиты NX и ASLR.)
Выше вы увидите, что то, что кажется повторяющимся сопоставлением в gdb
, на самом деле соответствует разным сопоставлениям с разными разрешениями. Текстовый сегмент отображается -только для чтения и исполняемый; сегмент данных отображается только для чтения -; BSS и куча отображаются на чтение -на запись. В идеале сегмент данных, BSS и куча не являются исполняемыми, но в этом примере отсутствует поддержка NX, поэтому они исполняемые. Каждая разделяемая библиотека получает собственное сопоставление для своего текстового сегмента, сегмента данных и BSS. Четвертое сопоставление — это не -доступный для чтения, не -доступный для записи, не -исполняемый сегмент, обычно используемый для защиты от переполнения буфера (, хотя, учитывая возраст используемого здесь ядра и библиотеки C, это может быть что-то другое. ).
Смещение, если оно задано, указывает смещение данных в файле, которое не обязательно имеет много общего с его позицией в адресном пространстве. При загрузке на это распространяются ограничения выравнивания; например, заголовки программы libc-2.11.2.so
определяют два заголовка «LOAD»:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x00000000 0x00000000 0x13d2f4 0x13d2f4 R E 0x1000
LOAD 0x13e1cc 0x0013f1cc 0x0013f1cc 0x027b0 0x0577c RW 0x1000
(Используйте readelf -l
, чтобы увидеть это.)
Это может привести к множественным отображениям по одному и тому же смещению с разными виртуальными адресами, если секции, сопоставленные с сегментами, имеют разные флаги защиты. В случае stack6
:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x08048000 0x08048000 0x00604 0x00604 R E 0x1000
LOAD 0x000604 0x08049604 0x08049604 0x00114 0x00128 RW 0x1000
(Это также объясняет небольшой размер, показанный proc info mappings
для stack6
:: каждый заголовок запрашивает менее 4 КБ с выравниванием 4 КБ, поэтому он получает два сопоставления 4 КБ с одинаковым смещением по разным адресам.)
Пустые отображения соответствуют анонимным отображениям; подробности см. в man 5 proc
. Вам нужно разбить mmap
в gdb
, чтобы определить, чему они соответствуют.
Вы не можете видеть сопоставления ядра (, кроме устаревших vsyscall
на некоторых архитектурах ), потому что они не имеют значения с точки зрения процесса (они недоступны ).
Я не знаю лучшего gdb
варианта, я всегда использую /proc/$$/maps
.
См. Как запускаются программы :Исполняемые файлы ELF для получения подробной информации о формате ELF, читаемом ядром, и о том, как он отображается в распределении памяти; он содержит указатели на множество других справочных материалов.