相关疑难解决方法(0)

这个C程序如何编译和运行两个主要功能?

今天,在使用一个自定义库时,我发现了一种奇怪的行为.静态库代码包含调试main()功能.它不在#define旗帜内.所以它也存在于库中.它被用于链接到包含真实的另一个程序main().
当它们都链接在一起时,链接器不会抛出多个声明错误main().我想知道这是怎么发生的.

为简单起见,我创建了一个模拟相同行为的示例程序:

$ cat prog.c
#include <stdio.h>
int main()
{
        printf("Main in prog.c\n");
}

$ cat static.c
#include <stdio.h>
int main()
{
        printf("Main in static.c\n");
}

$ gcc -c static.c
$ ar rcs libstatic.a static.o
$ gcc prog.c -L. -lstatic -o 2main
$ gcc -L. -lstatic -o 1main

$ ./2main
Main in prog.c
$ ./1main
Main in static.c
Run Code Online (Sandbox Code Playgroud)

"2main"二进制文件如何找到main要执行的内容?

但是将它们编译在一起会产生多重声明错误:

$ gcc prog.c static.o
static.o: In function `main':
static.c:(.text+0x0): …
Run Code Online (Sandbox Code Playgroud)

c gcc program-entry-point

65
推荐指数
2
解决办法
6648
查看次数

在Unix上执行共享库

某些Unix共享库在从命令行调用时提供输出,就像它们是可执行文件一样.例如:

$ /lib/libc.so.6 
GNU C Library stable release version 2.13, by Roland McGrath et al.
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.5.2.
Compiled on a Linux 2.6.37 system on 2011-01-18.
[...]
Run Code Online (Sandbox Code Playgroud)

在我用C语言编写的共享库中,如何提供此输出?我现在已经执行了一个我刚刚创建的库,并且我遇到了一个段错误.

注意:我之前在unix.stackechange.com上问过这个问题 https://unix.stackexchange.com/questions/7066/executing-a-shared-library

c unix shared-libraries

16
推荐指数
1
解决办法
2573
查看次数

加载可执行文件或执行库

SO有大量 关于如何执行库或动态加载可执行文件的问题据我所知,所有答案都归结为:将可执行文件编译为位置无关代码并使用. 这非常有效,并且在 macOS 上仍然有效,直到glibc 最近发生更改,明确禁用了PIE。例如,此更改现在出现在 ArchLinux 上当前版本的 glibc (2.30) 中,并且尝试位置无关的可执行文件会出现错误:“无法动态加载位置无关的可执行文件”。dlopendlopendlopen

很难猜测是什么促使了如此彻底的改变,破坏了如此多的代码和有用的用例。(Patchwork 和 Bugzilla 的解释对我来说没有多大意义。)但是现在有一个问题:如果你想创建一个同时也是动态库的可执行文件该怎么办,反之亦然?

其中一条评论链接了一个解决方案。在这里为后代复制它:

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

const char service_interp[] __attribute__((section(".interp"))) = "/lib/ld-linux-x86-64.so.2";

extern "C" {

void lib_entry(void)
{
  printf("Entry point of the service library\n");    
  _exit(0);
}

}
Run Code Online (Sandbox Code Playgroud)

编译生成g++ -shared test-no-pie.cpp -o test-no-pie -Wl,-e,lib_entry一个也可以在 Linux 上执行的共享对象(动态库)。

我有两个问题:

  1. 如果我想传递命令行参数怎么办?如何修改此解决方案以使其接受arc,argv
  2. 还有其他选择吗?

linux executable glibc shared-libraries dlopen

9
推荐指数
1
解决办法
5865
查看次数

GCC - 如何重新排列堆栈?

我尝试构建一个使用pthreads和__m128 SSE类型的应用程序.根据GCC手册,默认堆栈对齐是16个字节.为了使用__m128,要求是16字节对齐.

我的目标CPU支持SSE.我使用的GCC编译器不支持运行时堆栈重组(例如-mstackrealign).我不能使用任何其他GCC编译器版本.

我的测试应用程序如下:

#include <xmmintrin.h>
#include <pthread.h>
void *f(void *x){
   __m128 y;
   ...
}
int main(void){
  pthread_t p;
  pthread_create(&p, NULL, f, NULL);
}
Run Code Online (Sandbox Code Playgroud)

应用程序生成异常并退出.经过简单的调试(printf"%p",&y)后,我发现变量y不是16字节对齐的.

我的问题是:如何在不使用任何GCC标志和属性(它们没有帮助)的情况下正确地重新对齐堆栈(16字节)?我应该在这个线程函数f()中使用GCC内联汇编程序吗?

c stack gcc sse pthreads

7
推荐指数
2
解决办法
4102
查看次数

如何编译ELF二进制文件以便它可以作为动态库加载?

这是一个理论问题.我知道也许最好的做法是使用共享库.但我遇到了这个问题,似乎无法在任何地方找到答案.

如何构建代码并用ELF格式编译一个C/C++程序,以便可以加载dlopen()

例如,如果一个可执行文件包含某个函数的实现,int test()并且我想从我的程序中调用此函数(并且最好得到函数的结果),如果可能的话,我该怎么做呢?

在伪代码中,我可以将其描述如下:

ELF可执行文件来源:

void main() {
    int i = test();
    printf("Returned: %d", i);//Prints "Returned: 5"
}

int test() {
    return 5;
}
Run Code Online (Sandbox Code Playgroud)

外部计划:

// ... Somehow load executable from above
void main() {
    int i = test();
    printf("Returned: %d", i);//Must print "Returned: 5"
}
Run Code Online (Sandbox Code Playgroud)

c linux elf dlopen dynamic-library

7
推荐指数
1
解决办法
1973
查看次数

如何向本机库添加功能,而不是向运行它的可执行文件添加功能?

语境

我已经完成了一个 Java 库,它使用带有 JNI 的 C 库。C库在linux中编译成.so文件。这个库需要cap_net_raw 能力

目标

执行一个没有额外权限的java 进程,该进程使用所述 java 库。将使用该库的实际进程是产品中已经存在的进程,我们不想授予它们更多权限。

为了测试这一点,我创建了一个jar并在使用和不使用sudo. 正如预期的那样,使用它会成功,但如果没有它,它就会失败。

重现测试的步骤

  1. 创建一个带有本地方法的java类,我们来调用它SocketTester.java
static {
    System.loadLibrary("SocketTester");
}
private native int socketTest();
Run Code Online (Sandbox Code Playgroud)
  1. socketTester.h使用命令生成文件
javac -h . SocketTester.java
Run Code Online (Sandbox Code Playgroud)
  1. 创建socketTester.c实现socketTester.h并需要该cap_net_raw功能的文件
  2. 编译用
gcc -o libSocketTester.so socketTester.c -shared -I/usr/lib/jvm/java-14-openjdk-amd64/include -I/usr/lib/jvm/java-14-openjdk-amd64/include/linux
Run Code Online (Sandbox Code Playgroud)
  1. 移动libSocketTester.so到/usr/lib
  2. 跑步
sudo ldconfig
Run Code Online (Sandbox Code Playgroud)
  1. 设置上限
cd /usr/lib
sudo setcap cap_net_raw=epi libSocketTester.so
Run Code Online (Sandbox Code Playgroud)
  1. 创建一个Test.java
public static void main(final String[] args) …
Run Code Online (Sandbox Code Playgroud)

java linux java-native-interface linux-capabilities

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

Linux可执行文件作为共享库

我正在尝试编译一个我想要用作共享库的可执行文件.当我清楚地编译并将其链接为"可执行文件" - 一切都很好 - 文件可以启动并正常工作.在这个阶段,我无法正确地链接其他库(日志中的大量重新定义).当我试图添加选项-Fpic -shared - 程序copiles成功,但从分段错误开始.如何让它同时成为可执行文件和"sharedlibrary"?

c++ linux gcc

5
推荐指数
1
解决办法
3871
查看次数

main 之外的分段错误

我正在处理一个大型的混合 C++/Fortran 项目。目前,可执行文件在启动时立即出现段错误,然后到达mainAFAICT。实际上在加载共享库之前。

一些输出:

$ ./myprog
Segmentation fault (core dumped)
$ gdb ./myprog core
GNU gdb (Ubuntu 7.7-0ubuntu3) 7.7
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For …
Run Code Online (Sandbox Code Playgroud)

c++ linker fortran segmentation-fault

5
推荐指数
1
解决办法
1436
查看次数

-pie到底做什么?

file /bin/ls并得到输出:

/ bin / ls:ELF 64位LSB共享库,x86-64,版本1(SYSV),动态链接,解释器/lib64/ld-linux-x86-64.so.2,用于GNU / Linux 2.6.32,剥离

我发现原因是我的gentoo正在使用-pie编译所有内容。

如果我将-nopie传递给gcc,我将得到正确的答案:

a.out:ELF 64位LSB可执行文件,x86-64,版本1(SYSV),动态链接,解释器/lib64/ld-linux-x86-64.so.2,用于GNU / Linux 2.6.32,未剥离

另外,我在构建.so时也发现了一些东西,它也是可执行文件。它使用-pie使DSO可执行。

在gcc的手册页中,它简要描述了:

-pie
在支持它的目标上生成与位置无关的可执行文件。

所以我想知道-pie到底在做什么?它如何使我的可执行文件被识别为共享对象?

c linux linker gcc code-generation

5
推荐指数
1
解决办法
2219
查看次数

使用 ifort 构建可执行共享库

有几个关于 SO 的精彩讨论已经涵盖了如何在 Linux 上生成可执行共享库:

在 C/C++ 中,这似乎相对简单;基本上有两个部分:

  1. 通过在库源代码中包含以下.interp内容,向 ELF添加一个部分(因为ld不包括共享库的部分):
    const char interp_section[] __attribute__((section(".interp"))) = "/path/to/dynamic/linker";
  2. 链接时设置适当的入口点,使用 -Wl,-e,entry_point

有谁知道如何使用 Fortran 编写的库来实现这一目标?具体来说,如何将一个.interp部分添加到使用编译的共享库中ifort

fortran shared-libraries intel-fortran

5
推荐指数
1
解决办法
75
查看次数

如何检查文件是否是DLL?

给定一个文件,我想检查这是一个DLL,还是共享对象(Linux)或dylib(Mac OS X),或者是不同的东西.我的主要兴趣是区分Linux和Mac OS X上的可执行文件和DLL.对于Windows,扩展应该足以解决我的问题.

我已经检查过神奇数字技术对Linux不起作用,因为可执行文件和共享对象都具有相同的编号.

c++ linux macos dll file-type

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