在C中,假设您有一个名为的变量variable_name.假设它位于0xaaaaaaaa,并且在该内存地址,您有整数123.换句话说,variable_name包含123.
我正在寻找关于措词" variable_name位于0xaaaaaaaa"的澄清.编译器如何识别字符串"variable_name"与该特定内存地址相关联?字符串"variable_name"是否存储在内存中?该编译器只是替代variable_name了0xaaaaaaaa,只要自己认为呢,如果是这样,是不是必须使用的内存,以使该替换吗?
我正在编写一个API作为内核模块,为设备驱动程序提供各种功能.我在mycode.c中写了三个函数.然后我构建并加载了模块,然后将mycode.h复制到<kernel>/include/linux中.在设备驱动程序中,我有一个#include <linux/mycode.h>并调用这三个函数.但是当我构建驱动程序模块时,我得到三个链接器警告,说明这些函数是未定义的.
笔记:
很明显,函数正在正确导出,内核知道它们的位置和位置.那么为什么司机不能看到他们的定义呢?知道我错过了什么吗?
编辑:我在这里找到了一些相关的信息: http ://www.kernel.org/doc/Documentation/kbuild/modules.txt
有时,外部模块使用来自另一个外部模块的导出符号.kbuild需要完全了解所有符号,以避免吐出有关未定义符号的警告.这种情况存在三种解决方案.
注意:建议使用顶级kbuild文件的方法,但在某些情况下可能不切实际.
使用顶级kbuild文件如果你有两个模块,foo.ko和bar.ko,其中foo.ko需要来自bar.ko的符号,你可以使用一个通用的顶级kbuild文件,所以这两个模块都是用同一个编译的建立.请考虑以下目录布局:
Run Code Online (Sandbox Code Playgroud)./foo/ <= contains foo.ko ./bar/ <= contains bar.ko The top-level kbuild file would then look like: #./Kbuild (or ./Makefile): obj-y := foo/ bar/ And executing $ make -C $KDIR M=$PWD will then do the expected and compile both modules with full任何一个模块的符号知识.
使用额外的Module.symvers文件构建外部模块时,会生成Module.symvers文件,其中包含未在内核中定义的所有导出符号.要从bar.ko访问符号,请将module.symvers文件从bar.ko的编译复制到构建foo.ko的目录.在模块构建期间,kbuild将读取外部模块目录中的Module.symvers文件,并且在构建完成时,将创建一个新的Module.symvers文件,其中包含已定义的所有符号的总和,而不是内核的一部分.
使用"make"变量KBUILD_EXTRA_SYMBOLS如果从另一个模块复制Module.symvers是不切实际的,则可以在构建文件中将空格分隔的文件列表分配给KBUILD_EXTRA_SYMBOLS.这些文件将在其符号表初始化期间由modpost加载.
但是对于所有这三种解决方案,为了让任何驱动程序使用我的API,它必须创建一个新的Makefile或直接访问我的Module.symvers文件?这看起来有点不方便.我希望他们能够#include我的头文件并且好好去.不存在其他替代方案吗?
TL; DR
我试图将这个问题作为一个简短的问题,但这是一个复杂的问题所以它最终会变长.如果您可以回答这方面的任何部分或提供任何建议或提示或资源或任何内容,那将非常有帮助(即使您没有直接解决我的所有问题).我现在正撞在墙上.:)
以下是我遇到的具体问题.请阅读下面的更多信息.
到目前为止我的方法
我正在尝试以特定的[未记录的]专有格式创建一个重定位文件,该格式主要基于ELF.我编写了一个工具,它接受一个ELF文件和一个部分链接文件(PLF)并处理它们以输出完全解析的rel文件.此rel文件用于根据需要加载/卸载数据以节省内存.该平台是一个32位PPC.一个问题是该工具是用c#编写的,但数据是针对PPC的,因此需要注意有趣的endian问题等.
我一直试图了解在用于解析未解析的符号等时如何处理重定位.到目前为止我所做的是从PLF复制相关部分,然后对于每个相应的.rela部分,我解析条目并尝试修复部分数据并根据需要生成新的重定位条目.但这就是我的困难所在.我离开了我的元素,这种事情似乎通常是由链接器和加载器完成的,所以没有很多好的例子可以借鉴.但是我发现了一些有帮助的东西,包括这一个.
所以发生的事情是:
我这样做的全部原因是因为有一个旧的过时不支持的工具不支持使用自定义部分,这是该项目的关键要求(出于内存原因).我们有一个自定义部分,其中包含一堆我们想要在启动后卸载的初始化代码(总计大约一兆).现有工具只是忽略该部分中的所有数据.
因此,虽然制作支持自定义部分的自己的工具是理想的,但如果有任何明智的想法以实现这一目标的另一种方式,我全都耳朵!我们已经提出了将.dtor部分用于我们的数据的想法,因为它几乎是空的.但这很麻烦,如果它阻止干净关闭,可能无论如何都无法工作.
重定位加示例代码
当我处理搬迁,我工作过的公式和信息在ABI文档中发现的HERE(约4.13节,第80ish),以及一些我已经挖出了其他代码示例和博客文章.但是这一切都让人感到困惑,并没有真正拼写出来,而且我发现的所有代码都有所不同.
例如,
所以,当我看到这种代码时,我该如何解读呢?
这是一个例子(来自这个来源)
case ELF::R_PPC64_ADDR14 : {
assert(((Value + Addend) & 3) == 0); …Run Code Online (Sandbox Code Playgroud) 分析这个问题,我dlopen在Linux上的动态加载()上下文中发现了一些关于弱符号解析行为的事情.现在我正在寻找管理这个的规范.
我们来举个例子吧.假设有一个程序a可以动态加载库b.so,并c.so按此顺序.如果c.so依赖于另外两个库foo.so(实际上libgcc.so在该示例中)和bar.so(实际上libpthread.so),则通常bar.so可以使用导出的符号来满足弱符号链接foo.so.但是,如果b.so还依赖foo.so但不依赖bar.so,那么这些弱的符号显然不会被联系起来bar.so.看起来好像foo.so墨水只是从a和b.so它们的所有依赖项中寻找符号.
这在某种程度上是有道理的,因为否则加载c.so可能会改变已经使用库的foo.so某些点的行为b.so.另一方面,在让我开始的问题中,这引起了相当多的麻烦,所以我想知道是否有办法解决这个问题.为了找到解决方法,我首先需要很好地理解在这些情况下如何指定符号解析的非常精确的细节.
在这些场景中定义正确行为的规范或其他技术文档是什么?
linux dynamic-linking dynamic-loading weak-linking symbol-table
我正在寻找解释.dynsymELF可执行文件的动态符号表().我可以.symtab使用该value属性成功解释符号表(每个符号16个字节),以表示符号和name属性的地址,以表示.strtab段中字符串开头的偏移量.但是我无法.dynsym使用相同的方法解释动态符号表().我用阿里的博客[1]作为参考.
我查看了Ali的另一个博客[2],但我不明白如何使用哈希表来解释动态符号表.显然,它与符号表使用的映射不同.我该如何解释动态符号表(.dynsym)?
另外,我正在查看的ELF可执行文件有两个部分,即.hash和.gnu.hash.我在哪个部分引用哈希值?
[1] http://blogs.oracle.com/ali/entry/inside_elf_symbol_tables
[2] http://blogs.oracle.com/ali/entry/gnu_hash_elf_sections
我们怎样才能看到python源代码的符号表?
我的意思是,Python在实际运行之前为每个程序创建一个符号表.所以我的问题是如何将符号表作为输出?
以下代码片段按预期工作:
def test():
print(f'local symbol table before exec : {locals()}')
exec('a = 0')
print(f'local symbol table after exec : {locals()}')
test()
# printed result:
# local symbol table before exec : {}
# local symbol table after exec : {'a': 0}
Run Code Online (Sandbox Code Playgroud)
但是,一旦我a = 1在test函数末尾添加了符号定义语句,该exec语句似乎对本地符号表没有影响:
def test():
print(f'local symbol table before exec : {locals()}')
exec('a = 0')
print(f'local symbol table after exec : {locals()}')
a = 1
test()
# printed result:
# local symbol table …Run Code Online (Sandbox Code Playgroud) 我试图在Linux Mint 16 x64上运行可执行文件,这是为Ubuntu 12 x64编译的.可执行文件在运行时动态使用Qt 5.1.1.我收到错误:
loaded the dummy plugin
loaded the Linux plugin
updating server status
./executableName: symbol lookup error: ./executableName: undefined symbol: _ZN18QXmlDefaultHandlerC2Ev
Run Code Online (Sandbox Code Playgroud)
我跑的时候
ldd executableName | grep "not found"
Run Code Online (Sandbox Code Playgroud)
搜索缺少的依赖项我没有得到任何结果; 似乎找到了所有动态依赖关系,但上面的未定义符号错误仍然存在.
思考?
据我所知,目标文件中的指令和数据都有地址.第一个数据项从地址0开始,第一个指令也从地址0开始.
重定位表包含有关在文件中的地址更改时需要更新的指令的信息,例如,如果文件与另一个文件链接在一起.在下面的示例中,行A将位于重定位表中.我不认为B会在重定位表中,因为标签"相等"的地址是相对于B.这些正确的假设是什么?
我知道符号表显示文件的标签以及尚未解析的标签.但是符号表包含哪些其他信息?
此外,当汇编程序将指令转换为二进制时,那些具有未解析引用的指令中放置了什么?B在这个例子中.
.data
TEXT: .asciiz "Foo"
.text
.global main
main:
li t0, 1
beq t0, 1, equal #B
equal:
la a0, TEXT
jal printf #A
Run Code Online (Sandbox Code Playgroud) symbol-table ×10
c ×3
elf ×2
linux ×2
python ×2
assembly ×1
c++ ×1
compilation ×1
dynamic ×1
exec ×1
kernel ×1
linker ×1
memory ×1
module ×1
object-files ×1
opcode ×1
python-3.x ×1
qt ×1
relocation ×1
variables ×1
weak-linking ×1