标签: x86-64

错误:ld.so:LD_PRELOAD中的对象'getpid.so'无法预加载:忽略

当我尝试使用LD_PRELOAD时,如下

LD_PRELOAD=getpid.so ./testpid
Run Code Online (Sandbox Code Playgroud)

我收到以下错误...

ERROR: ld.so: object 'getpid.so' from LD_PRELOAD cannot be preloaded: ignored.
Run Code Online (Sandbox Code Playgroud)

我使用编译getpid.so

gcc -Wall -fPIC -shared -o getpid.so getpid.c
Run Code Online (Sandbox Code Playgroud)

它包含以下代码......

// getpid.c
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

pid_t getpid(void)
{
    printf("Hello, world!\n");
    return syscall(SYS_getpid);
}
Run Code Online (Sandbox Code Playgroud)

tespid.c 使用getpid的constains代码,如下所示,并通过执行编译

gcc testpid -o testpid.c
Run Code Online (Sandbox Code Playgroud)

这可能是什么问题?为什么LD_PRELOAD不起作用?

// testpid.c
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

int main()
{
    printf( "pid = %d!\n", getpid() );

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

c linux x86-64 dynamic

12
推荐指数
1
解决办法
2万
查看次数

使用带有gcc的SSE指令而不使用内联汇编

我有兴趣使用x86-64与gcc的SSE向量指令,并且不想为此使用任何内联汇编.有没有办法在C中做到这一点?如果是这样,有人可以举个例子吗?

c gcc sse x86-64 simd

12
推荐指数
3
解决办法
8834
查看次数

你能在内核模式之外输入x64 32位"长兼容子模式"吗?

这可能完全重复 是否可以通过模式切换在64位进程中执行32位代码?,但这个问题是从一年前开始的,只有一个答案没有给出任何源代码.我希望得到更详细的答案.

我正在运行64位Linux(Ubuntu 12.04,如果重要的话).这里有一些代码可以分配页面,将一些64位代码写入其中,然后执行该代码.

#include <assert.h>
#include <malloc.h>
#include <stdio.h>
#include <sys/mman.h>  // mprotect
#include <unistd.h>  // sysconf

unsigned char test_function[] = { 0xC3 };  // RET
int main()
{
    int pagesize = sysconf(_SC_PAGE_SIZE);
    unsigned char *buffer = memalign(pagesize, pagesize);
    void (*func)() = (void (*)())buffer;

    memcpy(buffer, test_function, sizeof test_function);

    // func();  // will segfault 
    mprotect(buffer, pagesize, PROT_EXEC);
    func();  // works fine
}
Run Code Online (Sandbox Code Playgroud)

现在,纯粹是为了娱乐价值,我想做同样的事情,但buffer包含任意32位(ia32)代码,而不是64位代码.此页面意味着您可以通过将CS段描述符的位设置为"长兼容性子模式"来在64位处理器上执行32位代码LMA=1, L=0, D=1.我愿意将我的32位代码包装在执行此设置的序言/结尾中.

但我可以在Linux中以usermode进行此设置吗?(BSD/Darwin的答案也将被接受.)这是我开始对这些概念感到朦胧的地方.我认为解决方案涉及向GDT添加新的段描述符(或者是LDT?),然后通过lcall指令切换到该段.但是所有这些都可以在usermode中完成吗?

这是一个示例函数,在兼容性子模式下成功运行时应返回4,在长模式下运行时应返回8.我的目标是获取指令指针以获取此代码路径并从另一端出来%rax=4,而不会进入内核模式(或仅通过记录的系统调用执行此操作). …

linux kernel x86-64 compatibility-mode

12
推荐指数
1
解决办法
1593
查看次数

通过寄存器重命名器对寄存器进行微体系结构归零:性能与mov?

在一篇博客文章中读到,最近的X86微体系结构也能够在寄存器重命名器中处理常见的寄存器归零习语(例如将寄存器与自身对齐); 用作者的话来说:

"寄存器重命名器也知道如何执行这些指令 - 它可以将寄存器本身归零."

有人知道这在实践中是如何运作的吗?我知道有些ISA,如MIPS,包含一个在硬件中始终设置为零的架构寄存器; 这是否意味着在内部,X86微体系结构内部具有类似的"零"寄存器,以便在方便时映射到寄存器?或者我的心智模型对于这些东西如何在微体系结构上工作不太正确?

我之所以要问的原因是(从一些观察中)看来mov,在一个循环中,从一个包含零的寄存器到一个目的地,仍然比在循环内通过xor将寄存器归零要快得多.

基本上它发生的是我想根据条件将循环内的寄存器归零; 这可以通过提前分配架构寄存器来存储零(%xmm3在这种情况下),在整个循环期间不进行修改,并在其中执行以下内容来完成:

movapd  %xmm3, %xmm0
Run Code Online (Sandbox Code Playgroud)

或者用xor技巧代替:

xorpd   %xmm0, %xmm0
Run Code Online (Sandbox Code Playgroud)

(AT&T语法).

换句话说,选择是在循环之外提升常数零或在每次迭代中将其重新物化在其中.后者将实时架构寄存器的数量减少一个,并且通过处理器假设的特殊情况感知和处理xor成语,它似乎应该像前者一样快(特别是因为这些机器具有更多的物理无论如何,寄存器都比体系结构寄存器更重要,所以它应该能够在内部完成与我在程序集中所做的相同的工作,通过在内部提升常数零甚至更好,完全意识和控制自己的资源).但它似乎不是,所以我很好奇是否有任何具有CPU架构知识的人可以解释是否有一个很好的理论原因.

在这种情况下,寄存器由SSE寄存器发生,机器恰好是Ivy Bridge; 我不确定这些因素有多重要.

x86 assembly x86-64 cpu-architecture

12
推荐指数
2
解决办法
1447
查看次数

第一次学习汇编,这是说一个字大小是8字节?

当我打破主要时,它看起来像粗线是我正在创建和初始化的地方.我想我错了,我正试图从一本解释x86的书中检查x86_64程序集.这看起来很奇怪,我很确定我只是不明白,因为在本书中他说他会将单词和双字称为4字节.如果我能得到一个解释来帮助我的认知,我将不胜感激. __CODE__方法:http://ruby-doc.org/core-2.0.0/Enumerable.html#method-i-inject

size x86 assembly x86-64 cpu-word

12
推荐指数
1
解决办法
1万
查看次数

cmpq指令有什么作用?

我正在阅读syscall的以下定义:

.text
.globl syscall
.type   syscall,%function
.align 16
syscall:
    movq %rdi, %rax     /* Syscall number -> rax.  */
    movq %rsi, %rdi     /* shift arg1 - arg5.  */
    movq %rdx, %rsi
    movq %rcx, %rdx
    movq %r8, %r10
    movq %r9, %r8
    movq 8(%rsp),%r9    /* arg6 is on the stack.  */
    syscall         /* Do the system call.  */
    cmpq $-4095, %rax   /* Check %rax for error.  */
    jae __syscall_error     /* Branch forward if it failed.  */
    ret         /* Return to caller.  */

.size …
Run Code Online (Sandbox Code Playgroud)

x86 assembly x86-64

12
推荐指数
1
解决办法
2万
查看次数

如何在x86-64上优化C和C++中的函数返回值?

所述X86-64 ABI指定两个返回寄存器:raxrdx,在大小两个64位(8个字节).

假设x86-64是唯一的目标平台,这两个功能中的哪一个:

uint64_t f(uint64_t * const secondReturnValue) {
    /* Calculate a and b. */
    *secondReturnValue = b;
    return a;
}

std::pair<uint64_t, uint64_t> g() {
    /* Calculate a and b, same as in f() above. */
    return { a, b };
}
Run Code Online (Sandbox Code Playgroud)

考虑到针对x86-64的C/C++编译器的当前状态,会产生更好的性能吗?使用一个版本或其他版本是否存在性能方面的任何陷阱?编译器(GCC,Clang)总是能够优化std::pair返回raxrdx吗?

更新:通常,如果编译器优化std::pair方法(使用GCC 5.3.0Clang 3.8.0的二进制输出示例),则返回一对更快.如果f()没有内联,编译器必须生成代码以将值写入内存,例如:

movq b, (%rdi)
movq a, %rax
retq
Run Code Online (Sandbox Code Playgroud)

但是如果g()编译器满足要求:

movq a, %rax …
Run Code Online (Sandbox Code Playgroud)

c c++ performance x86-64 abi

12
推荐指数
1
解决办法
643
查看次数

GCC/Clang x86_64 C++ ABI在返回元组时不匹配?

在尝试优化x86_64上的返回值时,我注意到一件奇怪的事情.即,给出代码:

#include <cstdint>
#include <tuple>
#include <utility>

using namespace std;

constexpr uint64_t a = 1u;
constexpr uint64_t b = 2u;

pair<uint64_t, uint64_t> f() { return {a, b}; }
tuple<uint64_t, uint64_t> g() { return tuple<uint64_t, uint64_t>{a, b}; }
Run Code Online (Sandbox Code Playgroud)

Clang 3.8输出此汇编代码f:

movl $1, %eax
movl $2, %edx
retq
Run Code Online (Sandbox Code Playgroud)

这个用于g:

movl $2, %eax
movl $1, %edx
retq
Run Code Online (Sandbox Code Playgroud)

哪个看起来最佳.但是,使用GCC 6.1编译时,生成的程序集f与Clang输出相同,生成的程序集为g:

movq %rdi, %rax
movq $2, (%rdi)
movq $1, 8(%rdi)
ret
Run Code Online (Sandbox Code Playgroud)

看起来返回值的类型被GCC归类为MEMORY,而Clang归类为INTEGER.我可以确认将Clang代码与GCC代码链接这样的代码可能会导致分段错误(Clang调用GCC编译 …

c++ tuples x86-64 abi compiler-bug

12
推荐指数
2
解决办法
501
查看次数

为什么32字节的循环对齐使代码更快?

看看这段代码:

one.cpp:

bool test(int a, int b, int c, int d);

int main() {
        volatile int va = 1;
        volatile int vb = 2;
        volatile int vc = 3;
        volatile int vd = 4;

        int a = va;
        int b = vb;
        int c = vc;
        int d = vd;

        int s = 0;
        __asm__("nop"); __asm__("nop"); __asm__("nop"); __asm__("nop");
        __asm__("nop"); __asm__("nop"); __asm__("nop"); __asm__("nop");
        __asm__("nop"); __asm__("nop"); __asm__("nop"); __asm__("nop");
        __asm__("nop"); __asm__("nop"); __asm__("nop"); __asm__("nop");
        for (int i=0; i<2000000000; i++) {
                s += test(a, b, …
Run Code Online (Sandbox Code Playgroud)

performance benchmarking gcc x86-64 clang

12
推荐指数
1
解决办法
735
查看次数

长期未加签名

我想获得在c中添加两个无符号64位整数的进位位。如果需要,我可以使用x86-64 asm。码:

#include <stdio.h>

typedef unsigned long long llu;

int main(void){
  llu a = -1, b = -1;
  int carry = /*carry of a+b*/;
  llu res = a+b;
  printf("a+b = %llu (because addition overflowed), carry bit = %d\n", res, carry);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

c x86-64 integer-overflow addition extended-precision

12
推荐指数
2
解决办法
326
查看次数