我有以下C代码:
//declared at the beginning of the CAStar.c file:
int TERRAIN_PASSABLE = 1;
int TERRAIN_IMPASSABLE = 0;
int TERRAIN_SOME_WHAT_PASSABLE = 2;
Run Code Online (Sandbox Code Playgroud)
我注意到,对于这些变量中的任何一个,如果它们具有非零值,则"nm"命令将它们报告为类型"D"(初始化):
_TERRAIN_PASSABLE |00000008| D |
_TERRAIN_SOME_WHAT_PASSABLE|00000004| D |
Run Code Online (Sandbox Code Playgroud)
但是,初始化为0的那些报告为"B"(未初始化):
_TERRAIN_IMPASSABLE |00000000| B |
Run Code Online (Sandbox Code Playgroud)
为什么"初始化为0"和"用0以外的其他东西初始化"之间的区别?
我正在使用一些LLVM工具(如llvm-nm)作为静态库.即我复制源LLVM-nm.cpp,改名main(..)到llvm_nm(..)和它编译成静态库.我想将标准输出转发到我的文件.
我试过用下一种方法:
int out_fd, err_fd;
fpos_t out_pos, err_pos;
// redirect out
fflush(stdout);
fgetpos(stdout, &out_pos);
out_fd = dup(fileno(stdout));
freopen(outFilename, "w", stdout);
// execute
int ret = llvm_nm(argc_, argv_);
// restore output
fflush(stdout);
dup2(out_fd, fileno(stdout));
close(out_fd);
clearerr(stdout);
fsetpos(stdout, &out_pos);
Run Code Online (Sandbox Code Playgroud)
问题是它没有被转发(如果我添加printf()nm源代码而不是nm输出,它可以工作).我已经浏览了源码,我可以看到输出是使用llvm::outs()流完成的:
outs() << "Archive map" << "\n";
Run Code Online (Sandbox Code Playgroud)
而它的实现下一个方法:
/// outs() - This returns a reference to a raw_ostream for standard output.
00702 /// Use it like: outs() << "foo" …Run Code Online (Sandbox Code Playgroud) 那是我的代码:
int const const_global_init = 2;
int const const_global;
int global_init = 4;
int global;
static int static_global_init = 3;
static int static_global;
static int static_function(){
return 2;
}
double function_with_param(int a){
static int static_local_init = 3;
static int static_local;
return 2.2;
}
int main(){
}
Run Code Online (Sandbox Code Playgroud)
我生成main.o并尝试理解nm输出.我使用后nm main.o --printfile-name -a得到这个输出:
main.o:0000000000000000 b .bss
main.o:0000000000000000 n .comment
main.o:0000000000000004 C const_global
main.o:0000000000000000 R const_global_init
main.o:0000000000000000 d .data
main.o:0000000000000000 r .eh_frame
main.o:000000000000000b T function_with_param
main.o:0000000000000004 C global …Run Code Online (Sandbox Code Playgroud) 我已经构建了一个像这样的简单程序:
g++ application.cpp -o application.exe
然后执行命令;
ldd application.exe
...
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6
...
Run Code Online (Sandbox Code Playgroud)
我想列出libc库的所有符号:
nm /lib/x86_64-linux-gnu/libc.so.6
nm: /lib/x86_64-linux-gnu/libc.so.6: no symbols
nm --defined-only /lib/x86_64-linux-gnu/libc.so.6
nm: /lib/x86_64-linux-gnu/libc.so.6: no symbols
Run Code Online (Sandbox Code Playgroud)
为什么 nm 报告没有符号?如果 libc.so.6 不是库,而是某种指向实际库的链接,那么我如何才能找到实际库?
该nm实用程序在二进制符号列表不其文件中包括它是如何得到被命名任何解释或线索nm.
我想一些经验丰富的UNIX开发人员可以解决一些问题.
为什么nm实用程序这样命名?
我试图在可执行文件上处理nm或readelf -s的输出.但是,我无法在输出中区分静态函数.
这是我正在使用的:
test.c的
static int foo() {
int x = 6;
}
main() {}
Run Code Online (Sandbox Code Playgroud)
other.c
static int foo() {
int x = 5;
}
Run Code Online (Sandbox Code Playgroud)
我这样编译它们:
gcc -o test test.c other.c
Run Code Online (Sandbox Code Playgroud)
然后运行nm命令以获取所有符号:
nm test
Run Code Online (Sandbox Code Playgroud)
其中出现以下两个符号(对于我的静态函数):
00000000004004ed t foo
0000000000400500 t foo
Run Code Online (Sandbox Code Playgroud)
有没有一种方法可以区分特定foo函数出现的文件?或者我需要在编译之前做一些魔术才能让它发挥作用?
我应该补充一点,对于我的用例,我可以访问最终的二进制文件和它使用的目标文件,但我实际上无法自己构建它以确保它有一个符号表.
谢谢!
我有一些.fic专有格式的二进制文件,我有一个wd250hf64.so来自该供应商的包含 C++ 方法的文件 CComposanteHyperFile::HExporteXML(wchar_t* const path)
我可以使用 nm 看到
$ nm --demangle wd250hf64.so --defined-only
0000000000118c90 t CComposanteHyperFile::HExporteXML(wchar_t const*)
Run Code Online (Sandbox Code Playgroud)
未损坏的版本_ZN20CComposanteHyperFile11HExporteXMLEPKw与我使用本地 g++ 版本的版本相同
雷德夫给出
readelf -Ws wd250hf64.so | grep _ZN20CComposanteHyperFile11HExporteXMLEPK
19684: 0000000000118c90 119 FUNC LOCAL DEFAULT 11 _ZN20CComposanteHyperFile11HExporteXMLEPKw
Run Code Online (Sandbox Code Playgroud)
现在我尝试编写一个非常简单的程序
$ nm --demangle wd250hf64.so --defined-only
0000000000118c90 t CComposanteHyperFile::HExporteXML(wchar_t const*)
Run Code Online (Sandbox Code Playgroud)
但是当我用它编译时g++ toto.cpp -L. -l:wd250hf64.so
我有toto.cpp:(.text+0x10): undefined reference to 'CComposanteHyperFile::HExporteXML(wchar_t const*)'
我没有更多的运气dlopen
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int
main(int argc, char **argv)
{
void *handle; …Run Code Online (Sandbox Code Playgroud) 只是为了给你一些上下文,这是我想要实现的:我在一个共享对象文件中嵌入一个const char*,以便在.so文件本身中有一个版本字符串.我正在进行数据分析,这个字符串使我能够让数据知道产生它的软件版本.一切正常.
我遇到的问题是当我尝试直接读取.so库中的字符串时.我试着用
nm libSMPselection.so | grep _version_info
Run Code Online (Sandbox Code Playgroud)
得到
000000000003d968 D __SMPselection_version_info
Run Code Online (Sandbox Code Playgroud)
这一切都很好并且符合预期(char*被称为_SMPselection_version_info).但是我本来希望现在能够打开文件,寻找0x3d968并开始读取我的字符串,但我得到的只是垃圾.
当我打开.so文件并只是搜索字符串的内容(我知道它是如何开始)时,我可以在地址0x2e0b4找到它.在这个地址它就在那里,零终止并按预期.(我现在正在使用这种方法.)
我不是计算机科学家.有人可以向我解释为什么nm所示的符号值不正确,或者不同的是,如果它不是符号的地址,那么符号值是多少?
(顺便说一句,我在使用OSX 10.7的Mac上工作)
我正在研究ELF格式.我必须编写一个简单的nm函数(没有选项).我已经在输出上打印了符号的值和符号的名称.
这是nm输出:
value type name
0000000000600e30 D __DTOR_END__
Run Code Online (Sandbox Code Playgroud)
我有相同的,但没有'类型'.我正在使用ELF64_Sym结构,如下所示:
typedef struct {
Elf64_Word st_name;
unsigned char st_info;
unsigned char st_other;
Elf64_Half st_shndx;
Elf64_Addr st_value;
Elf64_Xword st_size;
} Elf64_Sym;
Run Code Online (Sandbox Code Playgroud)
我知道我必须使用st_info变量和这个宏:
#define ELF64_ST_TYPE(info) ((info) & 0xf)
Run Code Online (Sandbox Code Playgroud)
获取符号的类型.但是,符号类型可以是一个宏,如下所示:
NAME VALUE
STT_NOTYPE 0
STT_OBJECT 1
STT_FUNC 2
STT_SECTION 3
STT_FILE 4
STT_LOPROC 13
STT_HIOPROC 15
Run Code Online (Sandbox Code Playgroud)
我想知道如何从这些宏中获取由nm打印的字母,例如:
U, u, A, a, T, t, R, r, W, w
Run Code Online (Sandbox Code Playgroud) 我正在构建一个共享库(我们称之为"foo"),它使用另一个库(我们称之为"bar")."bar"使用OpenSSL中的一些函数.
这是问题浮出水面的地方.
"bar"被编译为静态库,看起来OpenSSL也是如此.所以当我链接库("foo")时,我包括:
libbar.alibcrypto.a和libssl.abuild命令看起来像这样:
g++ -Wl,-soname,libfoo.so -shared file1.o file2.o libbar.a \
libcrypto.a libssl.a -o libfoo.so
Run Code Online (Sandbox Code Playgroud)
但是,我收到了很多错误:
ld: ./obj/libbar.a(file1.c.o): in function initialize_openssl:
ssl.c:117: error: undefined reference to 'SSL_library_init'
Run Code Online (Sandbox Code Playgroud)
运行以下命令:
nm libssl.a | grep SSL_library_init
Run Code Online (Sandbox Code Playgroud)
产生以下输出:
00000000 T SSL_library_init
Run Code Online (Sandbox Code Playgroud)
显然,OpenSSL库没有任何问题.什么可能导致这样的事情?以下是用于构建OpenSSL的三个命令:
export cross=arm-linux-androideabi-
./Configure android --prefix=~/openssl-arm
make CC="${cross}gcc" AR="${cross}ar r" RANLIB="${cross}ranlib"
Run Code Online (Sandbox Code Playgroud)
编译过程完成没有任何错误,所以我完全感到困惑.
为什么我会收到引用明显存在的一堆OpenSSL符号的链接器错误?