标签: elf

如何通过elf加载器初始化全局变量

对于C中的全局变量

int aglobal = 5;

什么时候5被加载器转移到aglobal,它如何知道将5放入全局.

与函数中的静态声明相同的情况.喜欢

int afunc(){static int astatic = 8; 回归; }

global initialization elf

6
推荐指数
1
解决办法
1112
查看次数

在ELF文件中,如何确定_start的地址?

我一直在阅读ELF规范,无法确定程序入口点和_start地址从何而来。

似乎它们应该在一个相当一致的位置,但是我编写了一些琐碎的程序,而_start始终在另一个位置。

谁能澄清?

symbols elf

6
推荐指数
1
解决办法
2380
查看次数

ELF Android系统库中.rel.dyn部分的目的

我正在尝试处理.rel.plt某些Android系统库的部分,我可以很容易地找到函数的地址.

但是,我不确定该.rel.dyn部分的条目是做什么的.此部分是否也包含功能?.got.pltARM安卓库中缺少X86库中的表.不确定是否也需要这些.

android链接器代码提到系统库是预先链接并在固定地址加载的.如何处理.rel.plt.rel.dyn部分.

更广泛的问题是各地了解Android的基于ARM的系统库和.rel.dyn,rel.plt以及.got.plt部分用在预链接抛出的附加问题.

android elf prelink

6
推荐指数
1
解决办法
2309
查看次数

如何将ELF可执行文件转换为C代码?生成的C代码不必是人类可读的

我有一个ELF文件,我想将其反编译为C代码,并对生成的C代码进行简单的更改,然后将其重建为ELF。

反编译的C代码不需要完全可读。例如,如果混淆了变量和函数名称,那就可以了。

我可以使用哪些工具在Linux上完成此任务?

PS:如果C无法进行编译或不容易进行编译,尽管对汇编源进行调整对我来说非常困难,但我愿意考虑对汇编语言进行反编译。

更新:您可能会假设我正在使用以下C程序来获取我的a.outELF。现在,进一步假设我已经失去了这个原始C资料。所以,我现在想将其编译到(一个可能混淆),C其中我至少能够改变像琴弦的小东西源"world""Hello""Bye",或能扭转感if等语句

#include <stdio.h>
#include <string.h>

char buf[256];

const char *Hello = "Hello";
const char *Bye = "Bye";
const char *Who = "world";

char * greet(const char *greeting, const char *str) {
    strcpy(buf, greeting);
    strcat(buf, ", ");
    strcat(buf, str);
    strcat(buf, "!");
    return buf;
}

int main(int argc, char *argv[]) {
    int sayHello …
Run Code Online (Sandbox Code Playgroud)

c linux transform elf

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

重新使用已编译的.exe文件中的字符

很久以前,出于好奇,我尝试了十六进制编辑游戏"Dangerous Dave"的可执行文件.我查看了文件中找到的任何字符串,并进行了一些随机编辑,看看它是否真的会改变游戏中显示的文字.

我很惊讶地看到了结果,我现在使用十六进制编辑器和DOSBox重新创建了结果: 在此输入图像描述

可以看出,编辑字符串"ROMERO"中的两个字符"RO"导致4个字符被改变,结果变为"ZUMEZU".似乎程序正在重用这两个字符并在该字符串的开头和结尾打印它们.

这是什么原因?我的第一个猜测是尝试使可执行文件变小,但只是重用字符的代码可能需要比保存的2个字节更多的空间.它只是作者完成的技巧,还是只是一些编译器的巫术?

c binary dos elf

6
推荐指数
1
解决办法
58
查看次数

所有asm标签都成为可执行文件中的符号

使用时组装对象时nasm,我发现所有标签都包含在结果.o文件中的符号中,以及最终的二进制文件中.

这对于我已经声明的函数入口点GLOBAL和段开始部分(例如,对于该.text部分)是有意义的,但是标签简单地用作循环入口点并且所有这些都接近出现在输出文件中似乎很奇怪.除了泄漏内部实现细节之外,它还浪费了符号表中的空间.

例如,鉴于这个简短的装配程序:

GLOBAL _start
_start:
    xor eax, eax
normal_label:
    xor eax, eax
.local_label:
    xor eax, eax
    xor edi, edi
    mov eax, 231    ;  exit(0)
    syscall
Run Code Online (Sandbox Code Playgroud)

...建造使用:

nasm -f elf64 label-test.s
ld label-test.o -o label-test
Run Code Online (Sandbox Code Playgroud)

l对象文件和链接的可执行文件中生成(即本地)符号:

objdump --syms label-test.o

label-test.o:     file format elf64-x86-64

SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 label-test.s
0000000000000000 l    d  .text  0000000000000000 .text
0000000000000002 l       .text  0000000000000000 normal_label
0000000000000004 l       .text  0000000000000000 normal_label.local_label
0000000000000000 g       .text …
Run Code Online (Sandbox Code Playgroud)

x86 assembly linker nasm elf

6
推荐指数
1
解决办法
551
查看次数

全局const优化和符号插入

我正在尝试使用gcc和clang来查看它们是否可以优化

#define SCOPE static
SCOPE const struct wrap_ { const int x; } ptr = { 42 /*==0x2a*/ };
SCOPE struct wrap { const struct wrap_ *ptr; } const w = { &ptr };
int ret_global(void) { return w.ptr->x; }
Run Code Online (Sandbox Code Playgroud)

返回一个中间常量.

事实证明他们可以:

0000000000000010 <ret_global>:
   10:  b8 2a 00 00 00          mov    $0x2a,%eax
   15:  c3                      retq   
Run Code Online (Sandbox Code Playgroud)

但令人惊讶的是,移除静态会产生相同的装配输出.这让我很好奇,因为如果全局不是static它应该是可插入的并且用中间体替换引用应该防止全局变量上的位置.

确实如此:

#!/bin/sh -eu
: ${CC:=gcc}
cat > lib.c <<EOF
int ret_42(void) { return 42; }

#define SCOPE 
SCOPE const struct wrap_ { …
Run Code Online (Sandbox Code Playgroud)

c compiler-construction optimization linker elf

6
推荐指数
1
解决办法
126
查看次数

如果在同一翻译单元中调用函数,为什么需要重定位

因此,我有两个文件,一个是我的库,另一个是主要的prog可执行文件。图书馆:

static int internal1(int a, int b){
  return a + b;
}

namespace {
  int internal2(int a, int b){
    return a + b;
  }
}

void external2(int qq, int zz){

}

void external(int a, int b){
  external2(a, b);
  internal1(a, b);
  internal2(a, b);
}
Run Code Online (Sandbox Code Playgroud)

g++ -c -O0 -fPIC -o libtest.o libtest.cpp和 编译 g++ -shared -o libtest.so libtest.o

主要编:

extern void external(int a, int b);

int main(){
  external(1, 2);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译与 g++ -O0 -L. -ltest -o tester tester.cpp …

c++ linker g++ elf linkage

6
推荐指数
1
解决办法
148
查看次数

C++ ELF 目标文件符号表的函数列出了两次

我有一个源文件,它为一个非常大的类定义了移动构造函数。我在 Linux 系统上用 g++ 4.9.2 编译它。当我转储生成的 ELF 对象文件的符号表时,我看到 2 个移动构造函数的列表。两个列表具有相同的地址、相同的大小、相同的类型,并且链接器链接得很好,没有 ODR 违规。当我反汇编目标文件时,我只看到一个移动构造函数。我的结论是符号表有两个指向同一位置的条目。

同样的行为也会发生在这个特定类的构造函数中,该类是在同一个源文件中定义的。

我看到的唯一一个我不完全理解的编译标志是“-m64”,但我不知道这将如何影响符号表。

我也用 g++ 9.2.0 尝试过,现在符号表中有 3 个条目!其中两个指向同一个地址,第三个指向地址0x0,位于.text.unlikely部分,并被标记为[clone .cold]。

为什么是这样?


编辑:实际上,我可以在家里用一个很小的班级重现这个。

// class.h
class VeryLargeClass
{
    int data;

    public:
    VeryLargeClass(VeryLargeClass&&);
};

// class.cpp
#include "class.h"

VeryLargeClass::VeryLargeClass(VeryLargeClass&& other)
{
    data = other.data;
    other.data = 0;
}
Run Code Online (Sandbox Code Playgroud)

如果我用 编译它g++ -c -O3 class.cpp -o class.o,然后用 转储符号表,objdump -t class.o | c++filt我会得到以下内容: class.o: file format elf64-x86-64

SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 main.cc
0000000000000000 l    d  .text …
Run Code Online (Sandbox Code Playgroud)

c++ linux linker g++ elf

6
推荐指数
1
解决办法
1991
查看次数

为什么 PLT 存根开头需要“jmp”?

PLT 使用方式在 SystemV ABI 中指定(并在实践中实现),示意性如下:

# A call from somewhere in code is into a PLT slot
# (In reality not a direct call, in x64 typically an rip-relative one)
0x500:   
          call 0x1000   
...

0x1000:
   .PLT1: jmp [0x2000]  # the slot for f in the binary's GOT
          pushq $index_f
          jmp .PLT0
...
0x2000: 
# initially jumps back to .PLT to call the lazy-binding routine:
   .GOT1: 0x1005
# but after that is called:
          0x3000   # the address of the real implementation …
Run Code Online (Sandbox Code Playgroud)

assembly linker elf dynamic-linking got

6
推荐指数
1
解决办法
106
查看次数