Tag: gcc

GCC不在函数调用中保存/恢复保留寄存器

我在GCC有一个场景给我带来了问题。 我得到的行为不是我期望的行为。 总结一下这种情况,我提出了一些x86-64的新指令,这些指令是在硬件模拟器中实现的。 为了测试这些指令,我使用现有的C源代码并使用hex对新指令进行手动编码。 因为这些指令与现有的x86-64寄存器交互,所以我使用input / output / clobber列表来声明GCC的依赖关系。 发生的事情是,如果我调用一个函数,例如printf,则不会保存和恢复相关寄存器。 例如 register unsigned long r9 asm (“r9”) = 101; printf(“foo %s\n”, “bar”); asm volatile (“.byte 0x00, 0x00, 0x00, 0x00” : /* no output */ : “q” (r9) ); 101被分配给r9,并且内联汇编(在此示例中为假)依赖于r9。 这在没有printf的情况下正确运行,但是当它存在时,GCC不会保存和恢复r9,并且在调用自定义指令时会有另一个值。 我想也许GCC可能秘密地将赋值更改为变量 r9,但是当我这样做时 asm volatile (“.byte %0” : /* no output */ : “q” (r9) ); […]

如何在共享库中隐藏导出的符号名称

对于VC,我可以编写一个DEF文件并使用’NONAME’指令在dll的导出表中只保留序号。 我怎么能用gcc和ELF格式共享库做同样的事情? 或者,在ELF共享库中是否存在类似PE格式DLL中的序号的东西? 如果没有,我如何在共享库中隐藏导出的符号名称? ====================================== 更新:一些额外的描述: 在Windows中,您可以通过仅放置具有空名称的整数ID(序号)来导出函数。 为了显示它,dll导出表的正常布局如下所示: http : //home.hiwaay.net/~georgech/WhitePapers/Exporting/HowTo22.gif 。 “NONAME”看起来像这样: http ://home.hiwaay.net/~georgech/WhitePapers/Exporting/HowTo23.gif。 请注意,第二张图片中的函数名称为“N / A”。 以下是对它的完整解释:hxxp://home.hiwaay.net/~georgech/WhitePapers/Exporting/Exp.htm。 ====================================== 更新:非常感谢所有给我建议的人。 最后,我决定在linux / posix平台上使用静态库。 但是将小的“特殊部分”(使用一些不适合静态库的特性,例如:TLS Slot等)提取到普通的共享库中 。 因为小型普通共享库只做很少的事情,而且这些工作完全不敏感,所以不需要隐藏/隐藏它的API。 我认为这是解决我问题的最简单方法:-D

打印指针时出现奇怪的行为

我有以下代码: #include typedef struct { int* arg1; int arg2; } data; int main(int argc, char** argv) { data d; printf(“arg1: %p | arg2: %d\n”, d.arg1, d.arg2); } 输出最终是d.arg1不是NULL而d.arg2是0.例如: arg1: 0x7fff84b3d660 | arg2: 0 当我添加一个指向main的指针时,没有任何变化。 但是,当我打印指针时: #include typedef struct { int* arg1; int arg2; } data; int main(int argc, char** argv) { data d; int* test; […]

gccprimefaces内置函数

http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Atomic-Builtins.html 我相信以下代码会primefaces地增加var的值。 volatile int var = 0; __sync_fetch_and_add( &var, 1 ) 我将上述代码理解为以下逻辑 : 加载变量var的地址 将数字1写入变量varprimefaces – 通过寄存器/缓存,以某种方式 但是,我怀疑以下是否也是primefaces的 volatile int var = 0; volatile int num = 1; __sync_fetch_and_add( &var, num ) 因为它可能被解释为 加载变量var的地址 将变量num的值加载到寄存器中 将值写入变量var。 执行#2之后,但在#3之前,CPU /线程被中断,另一个CPU /线程更新变量num的值。 换句话说,当使用gcc的_ sync *()时,我可以使用变量而不是常量作为第二个参数吗? 它不会破坏primefaces性吗?

根据CERT编码规则POS49-C访问共享结构中的相邻成员时的竞争条件?

根据CERT编码规则POS49-C ,访问相同结构的不同字段的不同线程可能会发生冲突。 我使用常规的unsigned int而不是bit-field。 struct multi_threaded_flags { unsigned int flag1; unsigned int flag2; }; struct multi_threaded_flags flags; void thread1(void) { flags.flag1 = 1; } void thread2(void) { flags.flag2 = 2; } 我可以看到,即使是unsigned int,仍然存在竞争条件IF编译器决定使用加载/存储8个字节而不是4个字节。 我认为编译器永远不会这样做,并且竞争条件永远不会发生在这里,但这完全是我的猜测。 是否有关于此案例的明确定义的汇编/编译器文档? 我希望锁定,这是昂贵的,是这种情况恰好未定义的最后手段。 仅供参考,我使用gcc。

如何在运行时使用GCC和内联asm检测CPU体系结构类型?

我需要找到CPU的架构类型。 我没有访问/ proc / cpuinfo,因为机器正在运行syslinux。 我知道有一种方法可以使用内联ASM,但我相信我的语法不正确,因为我的变量iedx没有正确设置。 我和ASM一起苦苦挣扎,绝不是专家。 如果有人有任何提示或可以指出我正确的方向,我会非常感激。 static int is64Bit(void) { int iedx = 0; asm(“mov %eax, 0x80000001”); asm(“cpuid”); asm(“mov %0, %%eax” : : “a” (iedx)); if ((iedx) && (1 << 29)) { return 1; } return 0; }

什么确保操作数的读/写在扩展ASM的期望时间发生?

根据GCC的扩展ASM和汇编程序模板 ,为了使指令连续,它们必须位于同一个ASM块中。 我无法理解是什么提供了对具有多个语句的块中的操作数进行读写的调度或时序。 例如,在使用CPUID时需要保留EBX或RBX ,因为根据ABI,调用者拥有它。 关于EBX和RBX的使用存在一些悬而未决的问题,因此我们希望无条件地保留它(这是一项要求)。 因此需要将三个指令编码到单个ASM块中以确保指令的连续性(re:第一段中讨论的汇编器模板): unsigned int __FUNC = 1, __SUBFUNC = 0; unsigned int __EAX, __EBX, __ECX, __EDX; __asm__ __volatile__ ( “push %ebx;” “cpuid;” “pop %ebx” : “=a”(__EAX), “=b”(__EBX), “=c”(__ECX), “=d”(__EDX) : “a”(__FUNC), “c”(__SUBFUNC) ); 如果表示操作数的表达式在错误的时间点被解释,则__EBX将是保存的EBX (而不是CPUID的EBX ),如果启用了PIC,它可能是指向全局偏移表(GOT)的指针。 确切地说,表达式指定CPUID的%EBX到__EBX应该在PUSH %EBX之后发生(1); (2) CPUID ; 但(3) POP %EBX之前?

嵌入式C – 函数的参数太多(指针)

我试图在我的.cpp文件中调用以下宏: #define IAP_ROM_LOCATION 0x1FFF1FF1UL #define IAP_EXECUTE_CMD(a, b) ((void (*)())(IAP_ROM_LOCATION))(a, b) 但是,当我像这样调用所述函数时: IAP_EXECUTE_CMD(0, 0); 我得到一个错误,说明了太多的参数? 这怎么样? 我会很感激任何指针。 开发环境是Cortex-M3的GCC。

OS X版本(Lion或不是)检测的C宏?

是否有预定义的C宏来检测OS X的版本? 我知道__MACH__和__MACH__存在,但那些是二进制的。 是否有__APPLE_CC__的特定值表示狮子? 特别是,Lion在Lion中将getline()的定义添加到中,能够检测代码是否在Lion上进行编译以及解决编译错误是很好的。 具体来说,我指的是在Bash(XCode之外)中构建Unix C代码。

我可以将Thread Sanitizer用于OpenMP程序吗?

请考虑以下示例: #include int main () { int i = 0; #pragma omp parallel { #pragma omp critical { ++i; } } std::cout << i; } 使用g++ -fopenmp -fsanitize=thread和运行yield进行编译 警告:ThreadSanitizer:数据竞争(pid = 9576) 通过线程T1读取大小4在0x7ffdc170f600: #0 main._omp_fn.0(a.out + 0x000000400d20) #1 gomp_thread_start /build/gcc/src/gcc-5.2.0/libgomp/team.c:118(libgomp.so.1 + 0x00000000f42d) 先前通过线程T2在0x7ffdc170f600处写入大小4: #0 main._omp_fn.0(a.out + 0x000000400d35) #1 gomp_thread_start /build/gcc/src/gcc-5.2.0/libgomp/team.c:118(libgomp.so.1 + 0x00000000f42d) 位置是主线程的堆栈。 线程T1(tid = 9578,正在运行)由主线程创建: […]