标签: elf

a.out被ELF文件格式取代?

我有几个问题:

  • 为什么被a.out取代ELF
  • a.out格式中导致ELF文件格式提升的主要缺陷是什么?
  • 早期的核心转储基于a.out,但现在它们基于ELF.ELF提供的各种优势是什么?

unix linux coredump file-format elf

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

编译的C++类是什么样的?

有了汇编指令和C程序的一些背景知识,我可以看到编译函数的样子,但有趣的是我从来没有仔细考虑过编译后的C++类是什么样的.

bash$ cat class.cpp
#include<iostream>
class Base
{
  int i;
  float f;
};

bash$ g++ -c class.cpp
Run Code Online (Sandbox Code Playgroud)

我跑了:

bash$objdump -d class.o
bash$readelf -a class.o
Run Code Online (Sandbox Code Playgroud)

但是我得到的东西很难理解.

有人可以解释一下或提出一些好的起点.

c++ compiler-construction linker elf

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

正在运行的C程序可以访问自己的符号表吗?

我有一个linux C程序来处理发送到TCP套接字(绑定到特定端口)的请求.我希望能够通过对该端口的请求来查询C程序的内部状态,但我不想硬编码可以查询的全局变量.因此,我希望查询包含全局字符串名称和C代码,以在符号表中查找该字符串以查找其地址,然后通过TCP套接字将其值发回.当然,符号表不得被剥离.那么C程序甚至可以找到自己的符号表,是否有一个库接口用于查找给出其名称的符号?这是一个用gcc构建的ELF可执行C程序.

c linux gcc elf symbol-tables

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

是否可以在C中编写零成本异常处理?

g ++编译器具有零成本异常处理功能.据我所知,try什么都不做,但是当抛出异常时,会执行异常处理程序的子例程.像这样:

void foo() {
    try {
        bar(); // throws.
    } catch (Type exc) {
        baz();
    }
}
Run Code Online (Sandbox Code Playgroud)

伪代码(c-stylish)看起来像这样:

void foo() {
    bar();
    return;
catch1_Type:
    baz();
}
Run Code Online (Sandbox Code Playgroud)

bar()抛出.例程例程执行以下操作:

啊,返回地址是函数foo()!并且返回地址在第一个try-catch块中,我们抛出类型Type,因此异常处理程序例程位于地址foo + catch1_Type.所以清理堆栈让我们最终到达那里!

现在我的问题是:有没有办法在C中实现它?(可以是C99或更新,虽然我对gcc支持的C语言感兴趣).我知道我可以使用例如libunwind进行堆栈检查和遍历,虽然我不知道如何获取catch1_Type标签的地址.这可能是不可能的.

异常处理程序可能是一个不同的函数,同样可以,但是如何foo在另一个函数中获取stackframe的局部变量的地址?这似乎也是不可能的.

所以...有什么办法吗?我不想用这个进入汇编程序,但如果其他一切都失败也是可以接受的(尽管局部变量 - 伙计,如果使用不同的优化级别,你永远不会知道它们在哪里).

并且要明确 - 这个问题的目的是避免使用 setjmp/longjmp方法.

编辑:我发现了一个非常酷的想法,但完全不起作用:

gcc中的嵌套函数.他们能做什么?

  • 有权访问局部变量,
  • 有可能在父函数中转到本地标签!
  • 只要我们传递指向嵌套函数的指针,我们函数的被调用者就可以调用它,因此它可以被被调用者中的指针使用.

下行阻止我做任何零成本的事情:

  • 如果它们未使用,它们甚至会在-O0级别进行优化.我可以对此做些什么吗?如果可以的话,我可以在抛出异常时通过符号名称获取地址,并且它只是执行实现异常的工作,这些异常在不抛出时会花费成本...

c optimization exception-handling gnu-assembler elf

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

为什么objdump不显示.bss,.shstratab,.symtab和.strtab部分?

我目前正在C中执行自己的objdump实现.

对于我的-s选项,我必须显示ELF文件部分的全部内容.

我做得很好,但我显示的部分比"真正的"objdump更多.

实际上,它不会输出.bss,.shstrtab,.symtab和.strtab部分.

我正在环顾Shdr结构上的sh_flags值,但我找不到任何逻辑......

为什么objdump -s没有显示这些部分?

c elf objdump

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

阅读ELF部分的内容(以编程方式)

我试图检索ELF二进制文件中的附加部分的内容.此时,我使用以下代码检索每个部分的名称:

#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>

#pragma pack(push,1)
#pragma pack(pop)

#define EI_NIDENT       16

/* 32-bit ELF base types. */
typedef unsigned int Elf32_Addr;
typedef unsigned short Elf32_Half;
typedef unsigned int Elf32_Off;
typedef signed int Elf32_Sword;
typedef unsigned int Elf32_Word;

/* 64-bit ELF base types. */
typedef unsigned long long Elf64_Addr;
typedef unsigned short Elf64_Half;
typedef signed short Elf64_SHalf;
typedef unsigned long long Elf64_Off;
typedef signed int Elf64_Sword;
typedef unsigned int Elf64_Word;
typedef unsigned long long Elf64_Xword;
typedef …
Run Code Online (Sandbox Code Playgroud)

c linux ubuntu file elf

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

在Ubuntu 14.04下链接错误与`libopencv_highgui.so`,与`libtiff.so.5的奇怪结果

问题

我正在Ubuntu 14.04(64位)编译深度学习库Caffe.

Version: 2.4.8+dfsg1-2ubuntu1从ubuntu软件包服务器安装OpenCV():

sudo apt-get install libopencv-dev

Caffe使用CMake 2.8 编译.

链接错误:

链接CXX可执行文件

/usr/lib/x86_64-linux-gnu/libopencv_highgui.so.2.4.8:未定义引用`TIFFOpen@LIBTIFF_4.0'

信息来源

似乎找不到TIFF库的一些符号.我努力找到原因(没有运气).这是关于库的一些信息.

TIFF库链接 libopencv_highgui.so.2.4.8

$ ldd libopencv_highgui.so.2.4.8 | grep tiff

libtiff.so.5 => /usr/lib/x86_64-linux-gnu/libtiff.so.5(0x00007f978313b000)

导入符号 libopencv_highgui.so.2.4.8

$ readelf -s libopencv_highgui.so.2.4.8 | grep TIFFOpen

62:0000000000000000 0 FUNC GLOBAL DEFAULT UND TIFFOpen@LIBTIFF_4.0(9)

注意:@符号名称中只有一个.

$ nm -D libopencv_highgui.so.2.4.8 | grep TIFFOpen

你TIFFOpen

出口符号libtiff.so.5:

$ nm -D /usr/lib/x86_64-linux-gnu/libtiff.so.5

0000000000000000 A LIBTIFF_4.0

...

00000000000429f0 T TIFFOpen

...

$ readelf -s /usr/lib/x86_64-linux-gnu/libtiff.so.5|grep TIFFOpen …

c++ opencv elf dynamic-linking unresolved-external

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

将某些编译器生成的变量强制转换为特定的ELF节(使用gcc)

我将从最终的问题开始:在C中使用gcc,是否可以获得__func__(或等效地__FUNCTION__)存储在除.rodata(或其中任何-mrodata=点)或子部分之外的部分的值(?)?

完整的解释:

假设我有一个记录宏:

#define LOG(fmt, ...) log_internal(__FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)

(##当且仅当__VA_ARGS__列表为空时,在该一元上下文中使用的字符串连接运算符使用前面的逗号,从而允许使用带或不带参数的格式字符串.)

然后我可以正常使用宏:

void my_function(void) {
    LOG("foo!");
    LOG("bar: %p", &bar);
}
Run Code Online (Sandbox Code Playgroud)

可能打印(显然取决于实施log_internal):

foo.c:201(my_function) foo!
foo.c:202(my_function) bar: 0x12345678
Run Code Online (Sandbox Code Playgroud)

在这种情况下,格式字符串("foo""bar: %p")和预处理程序字符串("foo.c""my_function")是匿名只读数据,它们会.rodata自动放入该部分.

但是我说他希望他们去另一个地方(我在一个嵌入式平台上运行几乎所有来自RAM的速度,但内存限制正在推动将一些东西转移到ROM中).移动__FILE__和格式字符串"简单" :

#define ROM_STR(str) (__extension__({static const __attribute__((__section__(".rom_data"))) char __c[] = (str); (const char *)&__c;}))
#define LOG(fmt, ...) log_internal(ROM_STR(__FILE__), __LINE__, __func__, ROM_STR(fmt), ##__VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)

你不能放一个__attribute__匿名字符串,所以 …

c linker gcc elf

11
推荐指数
1
解决办法
4152
查看次数

理解__libc_init_array

我从http://newlib.sourcearchive.com/documentation/1.18.0/init_8c-source.html查看了__libc_init_array的源代码.
但我不太明白这个功能是做什么的.

我知道这些符号

/* These magic symbols are provided by the linker.  */
extern void (*__preinit_array_start []) (void) __attribute__((weak));
extern void (*__preinit_array_end []) (void) __attribute__((weak));
extern void (*__init_array_start []) (void) __attribute__((weak));
extern void (*__init_array_end []) (void) __attribute__((weak));
extern void (*__fini_array_start []) (void) __attribute__((weak));
extern void (*__fini_array_end []) (void) __attribute__((weak));
Run Code Online (Sandbox Code Playgroud)

在链接描述文件中定义.
链接器脚本的一部分可能如下所示:

  .preinit_array     :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  } >FLASH
  .init_array :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN …
Run Code Online (Sandbox Code Playgroud)

gcc startup elf linker-scripts newlib

11
推荐指数
3
解决办法
2万
查看次数

为什么除了GOT之外还存在PLT,而不仅仅是使用GOT?

据我所知,在典型的ELF二进制文件中,函数通过过程链接表(PLT)调用.函数的PLT条目通常包含跳转到全局偏移表(GOT)条目.此条目将首先引用一些代码将实际的函数地址加载到GOT中,并在第一次调用(lazy binding)后包含实际的函数地址.

确切地说,在延迟绑定之前,GOT入口指向PLT,跳转到GOT之后的指令.这些指令通常会跳转到PLT的头部,从那里调用一些绑定例程,然后更新GOT条目.

现在我想知道为什么有两个间接(调用PLT然后从GOT跳转到一个地址),而不是仅仅保留PLT并直接从GOT调用地址.看起来这可以节省跳跃和完整的PLT.您当然仍需要一些调用绑定例程的代码,但这可能在PLT之外.

有什么我想念的吗?额外PLT的目的是什么?


更新: 正如评论中所建议的那样,我创建了一些(伪)代码ASCII艺术来进一步解释我所指的内容:

据我所知,在懒惰绑定之前的当前PLT方案中就是这种情况:( PLT之间的一些间接printf由"......"表示.)

Program                PLT                                 printf
+---------------+      +------------------+                +-----+
| ...           |      | push [0x603008]  |<---+       +-->| ... |
| call j_printf |--+   | jmp [0x603010]   |----+--...--+   +-----+
| ...           |  |   | ...              |    |
+---------------+  +-->| jmp [printf@GOT] |-+  |
                       | push 0xf         |<+  |
                       | jmp 0x400da0     |----+
                       | ...              |
                       +------------------+
Run Code Online (Sandbox Code Playgroud)

...和懒惰绑定后:

Program                PLT                       printf
+---------------+      +------------------+      +-----+
| ...           |      | push [0x603008]  |  +-->| ... | …
Run Code Online (Sandbox Code Playgroud)

assembly executable elf dynamic-linking

11
推荐指数
1
解决办法
2265
查看次数