Мужчины, у вас memcmp(s1, s2, 4) генерирует вызов memcmp через PLT. Что-то не везет у вас с компилятором, ни с пятым ни с шестым. $ cat test.c #include <stdbool.h> #include <string.h> bool isBindir(const char *d, size_t dlen) { // Compare a string to a string literal. #define strLen(ss) (sizeof(ss "") - 1) #define memEq(s, ss) (memcmp(s, ss, strLen(ss)) == 0) #define strEq(s, ss) (s##len == strLen(ss) && memEq(s, ss)) #define startsWith(s, ss) (s##len >= strLen(ss) && memEq(s, ss)) #define endsWith(s, ss) (s##len >= strLen(ss) && memEq(s + s##len - strLen(ss), ss)) return endsWith(d, "bin/"); } int main() { return isBindir("/usr/bin/", strLen("/usr/bin/")) ? 0 : 1; } $ gcc -E test.c |grep \"bin/ return (dlen >= (sizeof("bin/" "") - 1) && (memcmp(d + dlen - (sizeof("bin/" "") - 1), "bin/", (sizeof("bin/" "") - 1)) == 0)); $ gcc -g -O2 -Wall test.c && objdump -D a.out |perl -ln00e 'print if /isBindir/' 0000000000400510 <isBindir>: 400510: 48 83 fe 03 cmp $0x3,%rsi 400514: 76 2a jbe 400540 <isBindir+0x30> 400516: 48 8d 7c 37 fc lea -0x4(%rdi,%rsi,1),%rdi 40051b: 48 83 ec 08 sub $0x8,%rsp 40051f: ba 04 00 00 00 mov $0x4,%edx 400524: be e0 05 40 00 mov $0x4005e0,%esi 400529: e8 c2 fe ff ff callq 4003f0 <memcmp@plt> 40052e: 85 c0 test %eax,%eax 400530: 0f 94 c0 sete %al 400533: 48 83 c4 08 add $0x8,%rsp 400537: c3 retq 400538: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1) 40053f: 00 400540: 31 c0 xor %eax,%eax 400542: c3 retq 400543: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 40054a: 00 00 00 40054d: 0f 1f 00 nopl (%rax) Я скачал себе седьмой компилятор, у него код генерируется нормальный. Одна инструкция cmp, как и надо! Это может быть связано не только с компилятором, а еще какой-то сортифай форс си-эйч-кей там был, может это он гадит. $ ~/gcc-7/bin/gcc -g -O2 -Wall test.c && objdump -D a.out |perl -ln00e 'print if /isBindir/' 0000000000400480 <isBindir>: 400480: 31 c0 xor %eax,%eax 400482: 48 83 fe 03 cmp $0x3,%rsi 400486: 76 0b jbe 400493 <isBindir+0x13> 400488: 81 7c 37 fc 62 69 6e cmpl $0x2f6e6962,-0x4(%rdi,%rsi,1) 40048f: 2f 400490: 0f 94 c0 sete %al 400493: f3 c3 repz retq 400495: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 40049c: 00 00 00 40049f: 90 nop В общем, для промышленного применения ПСПО уровня масштаба предприятия такой компилятор совершенно не годится. Да даже профилировать код не годится. Я пытаюсь получить более оптимальную последовательность инструкций, а он оказывается функцию вызывает! И сколько такого плохо скомпилированного кода в репозитории.
Спасибо. В gcc7 это безобразие исправлено, в gcc6 исправлять смысла нет. Пакеты со временем пересоберём.
Чота я подумал может это не сортифай форс, а макрос в glibc был, типа #define memcmp(dest, src, n) (__builtin_constant_p(n) ? glibc_inline_memcpy(dest,src,n) : __builtin_memcpy(dest,src,n)) Был там какой-то асм. И некоторое время казалось, что всё нормально. А потом макрос в glibc почикали, и оказалось что всё голое, никто ни за что не отвечает.
Что-то я не припоминаю макросов для memcmp в glibc. Не для memcpy, а именно для memcmp.