Articles of x86 64

双重下划线的含义在一开始

在标准库(glibc)中,我们可以看到使用前两个下划线定义的函数,例如sys/mman.h __mmap 。 什么目的? 而且我们怎样才能调用一个函数mmap ,这个函数似乎没有在任何地方声明。 我的意思是我们包含sys/mman.h ,但是sys/mman.h不声明mmap ,它只声明__mmap 。

在assembly中使用printf会导致空的输出

我尝试从我的汇编代码中使用printf ,这是一个最简单的例子,它应该打印hello到stdout: .section .rodata hello: .ascii "hello\n\0" .section .text .globl _start _start: movq $hello, %rdi #first parameter xorl %eax, %eax #0 – number of used vector registers call printf #exit movq $60, %rax movq $0, %rdi syscall 我用它来构build它 gcc -nostdlib try_printf.s -o try_printf -lc 当我运行它,似乎工作:stringhello打印出来,退出状态是0 : XXX$ ./try_printf hello XXX$ echo $? 0 XXX$ 但是,当我尝试捕捉文本时,很明显,有些东西不能正常工作: […]

编译器使用本地variables而不调整RSP

问题编译器:了解从小程序生成的汇编代码 ,编译器使用两个局部variables而不调整堆栈指针。 不调整RSP以使用局部variables似乎不会中断安全 ,因此编译器似乎依靠硬件在中断发生时自动切换到系统堆栈。 否则,出现的第一个中断会将指针指向堆栈并覆盖局部variables。 这个问题的代码是: #include <stdio.h> int main() { for(int i=0;i<10;i++){ int k=0; } } 该编译器生成的汇编代码是: 00000000004004d6 <main>: 4004d6: 55 push rbp 4004d7: 48 89 e5 mov rbp,rsp 4004da: c7 45 f8 00 00 00 00 mov DWORD PTR [rbp-0x8],0x0 4004e1: eb 0b jmp 4004ee <main+0x18> 4004e3: c7 45 fc 00 00 00 […]

生成LLVM C ++ API代码作为后端

在线LLVM演示页面可以select从源代码生成LLVM C ++ API代码作为后端。 但是,该演示页面现在已禁用。 我想知道如何使用可用的LLVM工具自己做。 我尝试了以下 clang++ -c -emit-llvm input.cpp -o input.ll llc -march=cpp -o input.ll.cpp input.ll 这给出了以下错误 llc: error: invalid target 'cpp'. 我正在使用LLVM / Clang版本3.2。

在gdb中检查C / C ++堆内存统计信息

我试图调查在Linux amd64 gdb内的C / C ++堆的状态,是否有一个很好的方法来做到这一点? 我试过的一种方法是“调用mallinfo()”,但不幸的是我不能提取我想要的值,因为gdb没有正确处理返回值。 我不是很容易编写一个函数来编译到我附加的过程的二进制文件中,所以我可以简单地实现我自己的函数,通过以这种方式在我自己的代码中调用mallinfo()来提取值。 是否有一个聪明的把戏,可以让我在飞行中做到这一点? 另一个select可能是find堆并遍历malloc头文件/空闲列表; 我很感激任何指向我可以开始寻找这些位置和布局的地方。 我一直在试图谷歌和解决这个问题约2个小时,我已经学到了一些迷人的东西,但仍然没有find我所需要的。

与位置无关的代码差异:x86与x86-64

我最近正在构build一个针对x86-64架构的特定共享库(ELF),如下所示: g++ -o binary.so -shared –no-undefined … -lfoo -lbar 这失败了以下错误: 在创build共享对象时,不能使用“对本地符号”进行重定位R_X86_64_32; 用-fPIC重新编译 当然,这意味着我需要重build它作为位置无关的代码,所以适合链接到共享库。 但是,这完全适用于x86,完全相同的构build参数。 所以问题是,如何重新定位x86不同于x86-64,为什么我不需要使用-fPIC编译前者?

x86-64 SysV ABI中的参数和返回值寄存器的高位允许垃圾吗?

x86-64 SysV ABI指定了函数参数如何在寄存器中传递( rdi第一个参数,然后是rsi等),以及如何传回整数返回值(在rax ,然后在rdx中传递非常大的值)。 但是,我不能find的是当传递小于64位的types时,参数或返回值寄存器的高位应该是什么。 例如,对于以下function: void foo(unsigned x, unsigned y); … x将在rsi以rdi和y传递,但它们只有32位。 rdi和rsi的高32位是否需要为零? 直觉上,我会承认是的,但所有的海湾合作委员会,铛和ICC 生成的代码具有特定的mov指令在开始零高位,所以它似乎编译器假设,否则。 同样,编译器似乎认为,如果返回值小于64位,则返回值rax的高位可能具有垃圾位。 例如,以下代码中的循环: unsigned gives32(); unsigned short gives16(); long sum32_64() { long total = 0; for (int i=1000; i–; ) { total += gives32(); } return total; } long sum16_64() { long total = 0; for (int i=1000; i–; […]

使用MAP_NORESERVE的mmap是否保留物理内存?

mmap文档在关于标志MAP_NORESERVE的说明如下。 不要为这个映射保留交换空间。 当交换空间被保留时,可以保证可以修改映射。 当交换空间未被保留时,如果没有可用的物理内存,则可以在写入时获得SIGSEGV。 我实际上想要的只是保留虚拟内存地址,并没有分配实际的物理内存。 这可以通过使用MAP_NORESERVE的mmap来完成吗? 如果我想要使用任何物理内存,我将使用MAP_NORESERVE通过mmap中的地址范围内的MAP_FIXED重新映射它。 总而言之,我希望内核不会为MAP_NORSERVE标志的mmap分配的内存预留任何物理页面。 它是否真的像这样工作,或者如果内核具有足够的物理内存,内核是否分配物理页面?

过程连接表和全局抵销表

我正在读PLT(过程连接表)和GOT(全局抵消表)这篇文章 。 虽然PLT的目的很清楚,但我仍然对GOT感到困惑。 我从文章中了解到,只有在共享库中声明为externvariables才需要GOT。 对于在共享库代码中声明为static全局variables,这不是必需的。 我的理解是正确的,还是我完全忽略了这一点。

用AT&T语法打印一个整数作为string,用Linux系统调用代替printf

我写了一个汇编程序来显示AT&T语法后的一个数字的阶乘。但它不工作。我的代码 .text .globl _start _start: movq $5,%rcx movq $5,%rax Repeat: #function to calculate factorial decq %rcx cmp $0,%rcx je print imul %rcx,%rax cmp $1,%rcx jne Repeat # Now result of factorial stored in rax print: xorq %rsi, %rsi # function to print integer result digit by digit by pushing in #stack loop: movq $0, %rdx […]