问题标签 [symbol-table]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
351 浏览

java - 带有堆栈和符号表的表达式解析器

首先,我会直截了当地说这是一个家庭作业问题。

我必须使用以下代码作为基础来构建表达式解析器: 编辑:

}

控制台输入类似于:

在这种情况下,控制台的输出将是 225。我的问题是我无法弄清楚如何在符号表的键和值之间拆分输入。用于输入键和值的 API 是void put(Key key, Value v)如果将键设置为 null,则删除该键。提前致谢。

0 投票
1 回答
20076 浏览

assembly - 目标文件中的符号表和重定位表

据我了解,目标文件中的指令和数据都有地址。第一个数据项从地址 0 开始,第一条指令也从地址 0 开始。

重定位表包含有关在文件中的地址更改时需要更新的指令的信息,例如,如果文件与另一个文件链接在一起。在下面的示例中,行 A 将位于重定位表中。我认为 B 不会在重定位表中,因为标签“等于”的地址是相对于 B 而言的。这些假设是否正确?

我知道符号表显示文件具有的标签以及尚未解析的标签。但是符号表还包含哪些其他信息?

此外,当汇编器将指令转换为二进制时,那些具有未解析引用的指令中放置了什么?本例中为 B。

0 投票
3 回答
11911 浏览

reverse-engineering - 处理 ELF 重定位 - 了解重定位、符号、节数据以及它们如何协同工作

TL;博士

我试图把这个问题变成一个简短的问题,但这是一个复杂的问题,所以它最终变得很长。如果您可以回答其中的任何部分或提供任何建议或提示或资源或任何东西,那将非常有帮助(即使您没有直接解决我的所有问题)。我现在正用头撞墙。:)

这是我遇到的具体问题。阅读下文了解更多信息。

  • 我正在寻找有关如何处理重定位条目和更新节数据中未解析符号的指导。我只是不明白如何处理我从搬迁和部分等中提取的所有信息。
  • 我也希望了解链接器遇到重定位时发生了什么。尝试正确实现重定位方程并以正确的方式使用所有正确的值是非常具有挑战性的。
  • 当我遇到操作码和地址和符号等时,我需要了解如何处理它们。我觉得我错过了一些步骤。
  • 我觉得我不太了解符号表条目如何与重定位交互。我应该如何使用符号的绑定、可见性、值和大小信息?
  • 最后,当我用可执行文件使用的解析数据和新的重定位条目输出我的文件时,数据都是不正确的。我不确定如何跟踪所有搬迁并提供所有必要的信息。可执行文件对我有什么期望?

到目前为止我的方法

我正在尝试以严重基于 ELF 的特定 [未记录] 专有格式创建重定位文件。我编写了一个工具,它采用 ELF 文件和部分链接文件 (PLF) 并处理它们以输出完全解析的 rel 文件。此 rel 文件用于根据需要加载/卸载数据以节省内存。该平台是 32 位 PPC。一个问题是该工具是用 c# 为 Windows 编写的,但数据是为 PPC 准备的,因此需要注意一些有趣的字节序问题等。

我一直在尝试了解在用于解析未解析的符号等时如何处理重定位。到目前为止,我所做的是从 PLF 复制相关部分,然后对于每个相应的 .rela 部分,我解析条目并尝试修复部分数据并根据需要生成新的重定位条目。但这就是我的困难所在。我在这里已经脱离了我的元素,这种事情似乎通常由链接器和加载器完成,所以没有很多好的例子可以借鉴。但我发现了一些有帮助的,包括THIS ONE

所以正在发生的事情是:

  1. 从 PLF 复制部分数据以用于 rel 文件。我只对 .init(无数据)、.text、.ctors、.dtors、.rodata、.data、.bss(无数据)和我们正在使用的另一个自定义部分感兴趣。
  2. 遍历 PLF 中的 .rela 部分并读入 Elf32_Rela 条目。
  3. 对于每个条目,我提取 r_offset、r_info 和 r_addend 字段,并从 r_info(符号和 reloc 类型)中提取相关信息。
  4. 从PLF 的符号表中,我可以得到symbolOffset、symbolSection 和symbolValue。
  5. 从 ELF 中,我得到了 symbolSection 的加载地址。
  6. 我计算 int localAddress = ( .relaSection.Offset + r_offset )。
  7. 我从 r_offset 处的 symbolSection 内容中获得了 uint relocValue。
  8. 现在我有了我需要的所有信息,所以我打开 reloc 类型并处理数据。These are the types I support:
    R_PPC_NONE
    R_PPC_ADDR32
    R_PPC_ADDR24
    R_PPC_ADDR16
    R_PPC_ADDR16_LO
    R_PPC_ADDR16_HI
    R_PPC_ADDR16_HA
    R_PPC_ADDR14
    R_PPC_ADDR14_BRTAKEN
    R_PPC_ADDR14_BRNTAKEN
    R_PPC_REL24
    R_PPC_REL14
    R_PPC_REL14_BRTAKEN
    R_PPC_REL14_BRNTAKEN
  9. 怎么办??我需要更新部分数据并构建伴随的重定位条目。但我不明白需要做什么以及如何去做。

我这样做的全部原因是因为有一个旧的过时的不受支持的工具不支持使用自定义部分,这是该项目的关键要求(出于内存原因)。我们有一个自定义部分,其中包含我们要在启动后卸载的一堆初始化代码(总共大约一个兆)。现有工具只是忽略该部分中的所有数据。

因此,虽然制作我们自己的支持自定义部分的工具是理想的,但如果有任何好的想法可以通过另一种方式来实现这一目标,我会全力以赴!我们一直在考虑使用 .dtor 部分来存储我们的数据,因为它几乎是空的。但这很麻烦,如果它阻止了干净的关机,它可能无论如何都不起作用。


重定位加上示例代码

当我处理重定位时,我正在处理 ABI 文档中的方程式和信息大约第 4.13 节,第 80 页)以及我挖掘的许多其他代码示例和博客文章。但这一切都如此令人困惑,并没有真正拼写出来,而且我发现的所有代码的作用都有些不同。

例如,

  • R_PPC_ADDR16_LO --> half16: #lo(S + A)
  • R_PPC_ADDR14_BRTAKEN --> low14*: (S + A) >> 2
  • ETC

那么当我看到这种代码时,我该如何破译呢?

这是一个示例(来自此来源

这是另一个例子中的一些(这里

还有另一个例子(来自这里

我真的很想了解这些人在这里所做的魔法以及为什么他们的代码看起来并不总是一样的。我认为一些代码假设数据已经被正确屏蔽(用于分支等),而一些代码则没有。但我一点也不明白。


遵循符号/数据/重定位等

当我在 hexeditor 中查看数据时,我看到一堆“48 00 00 01”。我发现这是一个操作码,需要使用重定位信息进行更新(这专门用于 'bl' 分支和链接),但我的工具不能在绝大多数和我所做的那些上运行更新中有错误的值(与过时工具制作的示例相比)。显然,我错过了该过程的某些部分。

除了节数据之外,还有一些额外的重定位条目需要添加到 rel 文件的末尾。这些包括内部和外部搬迁,但我还没有弄清楚这些。(两者有什么区别,什么时候使用其中一个?)

如果您在该文件的末尾附近查看function RuntimeDyldELF::processRelocationRef,您会看到正在创建一些重定位条目。他们还制作存根函数。我怀疑这对我来说是缺失的环节,但它就像泥泞一样清晰,我什至没有关注它。

当我在每个重定位条目中输出符号时,它们每个都有一个绑定/可见性 [Global/Weak/Local] [Function/Object] 和一个值、一个大小和一个部分。我知道该部分是符号所在的位置,并且值是该部分中符号的偏移量(或者它是虚拟地址?)。大小就是符号的大小,但这重要吗?也许全局/弱/本地对于确定它是内部还是外部重定位很有用?

也许我正在谈论创建的这个重定位表实际上是我的 rel 文件的符号表?也许这个表将符号值从虚拟地址更新为节偏移量(因为这是可重定位文件中的值,而 PLF 中的符号表基本上在可执行文件中)?


一些资源:

  1. 关于搬迁的博客: http: //eli.thegreenplace.net/2011/08/25/load-time-relocation-of-shared-libraries/
  2. 最后提到操作码:http ://wiki.netbsd.org/examples/elf_executables_for_powerpc/
  3. 我相关的未回答问题:ELF Relocation reverse engineering

哇!这是一个问题。恭喜你做到了这一步。:) 提前感谢您能给我的任何帮助。

0 投票
1 回答
784 浏览

python - Python 在同一个线程上定义了我的类两次

我曾假设在 Python 中如果我做一些

如果我用一些明确删除 A,这个“hi”只会被打印不止一次del A

在我稍大的项目中,我有以下代码(名称已更改):

它产生这个输出:

所以在同一个线程上,相同的类级代码被执行两次。当我从来没有的时候,这怎么可能del A?该代码以前有效,但我没有承诺缩小破坏它的更改范围。

使用 MY_DICT 而不是 A.MY_DICT 的相同代码同样失败,并且 PyDev 在撰写本文时已经告诉我这不起作用,我非常有信心发生了一些可疑的事情。

0 投票
1 回答
234 浏览

c++ - 编译器构造:处理对无序符号的引用

我有龙书,但它似乎没有处理那个话题......

在最现代的语言中,即使它们在代码中的出现是无序的,也可以使用某些变量。

例子

plonk在函数之后声明变量并不重要。

问题
是否有任何最佳实践/有用的模式来实现这一点?我想到了两种方法:

  1. 解析时为看不见的符号添加虚拟符号。解析声明时,这些虚拟对象将被它们的真实符号替换。解析后,我们可以检查是否有假人,如果有则输出错误。

  2. 解析时不要做任何符号的事情,而只创建 AST。在通过 AST 解析步骤并根据节点添加符号之后。例如,类节点添加子节点的符号并在之后处理它们。例如,语句块逐步遍历子级并在处理子级之前立即添加符号。

我希望方法 1. 对于“导入其他编译单元”之类的东西更容易,也更有用。

编辑:
我在方法 1 中看到的一个问题是需要对有序符号进行某种处理。例如,对于一个函数,在使用本地符号之前是不可能使用它的。

0 投票
1 回答
702 浏览

java - 使用 Java 反转索引

今天,我正在与一个使用 Java 从文本文件创建索引的客户端合作。我需要做的就是反转索引以从头到尾重新创建文本。现在,我似乎遇到的问题是从哪里开始以及如何执行每一步。到目前为止,我已经尝试创建一个单词数组并遍历我的符号表并将每个键分配给数组。然后我最终只从索引中得到了一个单词列表。出于某种原因,这个问题让我觉得很愚蠢,因为它似乎应该是一个简单的解决方案。我似乎想不出任何有效的想法来让我开始重新创作这个故事。我在这里包括了来源:

}

0 投票
1 回答
79 浏览

php - 奇怪的行为,通过引用分配未定义的变量

我只是在探索符号表和变量容器如何与引用一起工作。我发现

不会抛出“未定义变量:b in ...”的通知,而

做。

为什么?

0 投票
1 回答
84 浏览

c++ - 防止意外的对象不兼容?

TL;博士

防止在不同编译单元中控制条件编译的共享的、可能是模板化的头文件的预处理器指令中的编译器参数拼写错误导致二进制不兼容?

前任。

基本故事

最近遇到一个奇怪的bug:症状是单个SIGSEGV,重新编译后似乎总是出现在同一个位置。这让我相信发生了某种内存损坏,而实际的底层指针根本不是指针,而是一些数据部分。

我将您从漫长而艰苦的旅程中拯救出来,这几乎需要两个原本非常好的工作日来追踪问题。说够了,Valgrind、GDB、nm、readelf、电栅栏、GCC的栈砸保护,然后再一些措施/方法/途径都失败了。

在彻底的毁灭中,我的注意力转向了构建过程中最精细的细节,这类似于:

  • 建一个小图书馆。
  • 建立一个大型图书馆,使用小型图书馆。
  • 构建大型库的测试套件。

只有当大型库用作静态库或动态库依赖项(即动态链接器自动加载它,没有 dlopen)时才会出现问题。库的所有代码都简单地包含在测试中的测试用例,一切正常:这是最重要的线索。

解决方案”

最后,结果证明这是最简单的事情:一个(!)错字。

事实证明,编译标志在测试套件中只有一个字符,而大型库:控制小型库行为的定义拼写错误。关键信息点:小型图书馆有一些模板。这些在每种情况下都直接使用,无需事先明确实例化。切换标志时,其中一个模板类的内容发生了变化:在定义标志的情况下,某些数据字段根本不存在!链接器没有注意到这一点。(由于类是模板化的,因此生成的符号很弱。)代码使用了动态强制转换,受此问题影响的类继承自损坏的类 -> 事情发生了变化。

我的问题如下:您将如何防范此类问题?是否有任何工具或解决方案可以解决这个特定问题?

未来证明

我想到了两件事,并且相信无法在目标文件级别上建立任何保护:

  • 1:将实现为预处理器符号的选项保存在某个定义明确的位置,最好通过单独的构建步骤提取。提供检查脚本,使用它来检查所有编译器定义和用户代码中的定义。将此检查集成到构建过程中。可能使用 Levenshtein distance 或类似的方法来检查拼写错误。昂贵,脚本/解决方案可能会变得复杂。类似标志可能存在问题(但为什么有它们?),附加文件必须伴随已编译的库代码。(好吧,也许对于 DWARF 2,这是不真实的,但我们假设我们不希望这样。)
  • 2:集中构建选项:便宜,自定义选项保持打开状态(想想 makefile.local),但会产生单体怪物,强大的项目耦合。

我想继续熄灭一些可能在某些读者中燃烧的可能引发火焰的余烬:“不要使用预处理器符号”在这里不是一个选项。

  • 条件编译确实在高性能代码中占有一席之地,并且使用模板和 enable_if-s 做所有事情都会不必要地使事情变得过于复杂。虽然上述解决方案通常是不可取的,但它可能会出现在开发过程中。
  • 请假设你无法控制这种情况,假设你有遗留代码,假设你可以强迫自己避免回避。
  • 如果这些都不起作用,请概括为 ABI 不兼容性检测,尽管这可能会过度扩大问题的范围。

我知道:

0 投票
1 回答
3102 浏览

compiler-construction - 'yylval' 的 flex 和 bison 冲突类型

编译 lex 程序时出现错误:'yylval' extern YYSTYPE *yylval 的类型冲突;

知道如何纠正这个吗?这是 lex 代码

0 投票
1 回答
1794 浏览

python - 什么时候在 Python 中创建符号表

UnboundLocalError:分配前引用的局部变量“a”

我只是想确定为什么第二种情况是正确的,而第一种情况是错误的。

函数的执行引入了一个新的符号表,用于函数的局部变量。更准确地说,函数中的所有变量赋值都将值存储在本地符号表中;而变量引用首先在局部符号表中查找,然后在封闭函数的局部符号表中查找,然后在全局符号表中查找,最后在内置名称表中查找。

当解释器通过函数的定义时,它会创建一个符号表。它首先将“a”视为全局(由于 print(a)),然后在本地符号表中创建“a”(由于赋值)。

因此,在实际执行函数时,'a' 是一个没有绑定的局部变量。因此错误。

我对符号表的推理是否正确?

更新:分配后添加全局:

语句是否从函数的本地符号表中global a删除名称?'a'square