在共享库中混合 PIC 和非 PIC 对象
这个问题与这个问题及其答案相关。
我刚刚发现我正在开发的构建中有一些丑陋之处。情况有点像下面这样(以 gmake 格式编写);请注意,这特别适用于 sparc 和 x86 硬件上的 32 位内存模型:
OBJ_SET1 := some objects
OBJ_SET2 := some objects
# note: OBJ_SET2 doesn't get this flag
${OBJ_SET1} : CCFLAGS += -PIC
${OBJ_SET1} ${OBJ_SET2} : %.o : %.cc
${CCC} ${CCFLAGS} -m32 -o ${@} -c ${<}
obj1.o : ${OBJ_SET1}
obj2.o : ${OBJ_SET2}
sharedlib.so : obj1.o obj2.o
obj1.o obj2.o sharedlib.so :
${LINK} ${LDFLAGS} -m32 -PIC -o ${@} ${^}
显然,它可以在共享对象中混合使用和不使用 PIC 编译的对象(这已使用多年)。我对 PIC 的了解不够,不知道这是否是一个好主意/聪明,我的猜测是在这种情况下它是不需要的,而是它正在发生,因为有人在处理时没有足够关心找到正确的方法来做到这一点关于构建的新内容。
我的问题是:
- 这安全吗?
- 这是一个好主意吗?
- 结果可能会出现什么潜在问题?
- 如果我将所有内容都切换到 PIC,是否有任何我可能需要注意的不明显的问题。
This question is related to this one as well as its answer.
I just discovered some ugliness in a build I'm working on. The situation looks somewhat like the following (written in gmake format); note, this specifically applies to a 32-bit memory model on sparc and x86 hardware:
OBJ_SET1 := some objects
OBJ_SET2 := some objects
# note: OBJ_SET2 doesn't get this flag
${OBJ_SET1} : CCFLAGS += -PIC
${OBJ_SET1} ${OBJ_SET2} : %.o : %.cc
${CCC} ${CCFLAGS} -m32 -o ${@} -c ${<}
obj1.o : ${OBJ_SET1}
obj2.o : ${OBJ_SET2}
sharedlib.so : obj1.o obj2.o
obj1.o obj2.o sharedlib.so :
${LINK} ${LDFLAGS} -m32 -PIC -o ${@} ${^}
Clearly it can work to mix objects compiled with and without PIC in a shared object (this has been in use for years). I don't know enough about PIC to know whether it's a good idea/smart, and my guess is in this case it's not needed but rather it's happening because someone didn't care enough to find out the right way to do it when tacking on new stuff to the build.
My question is:
- Is this safe
- Is it a good idea
- What potential problems can occur as a result
- If I switch everything to PIC, are there any non-obvious gotchas that I might want to watch out for.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
忘了我什至写过这个问题。
首先是一些解释:
答案:
更新 (4/17)
我已经发现了我以前见过的一些崩溃的原因。举例来说:
...那么:
那个特定的示例可能不会最终崩溃,但这基本上是该组代码中存在的情况。如果它确实崩溃,它很可能出现在析构函数中,通常是双重释放错误。
许多年前,他们在构建中添加了 -zmuldefs 来消除多重定义的符号错误。编译器发出用于在全局对象上运行构造函数/析构函数的代码。
-zmuldefs
强制它们位于内存中的同一位置,但它仍然为 exe 和包含有问题标头的每个库运行一次构造函数/析构函数 - 因此是双重释放。Forgot I even wrote this question.
Some explanations are in order first:
The answers:
update (4/17)
I've since discovered the cause of some of the crashes I had seen previously. To illustrate:
... then:
That particular example may not end up crashing, but it's basically the situation that had existed in that group's code. If it does crash it'll likely be in the destructor, usually a double-free error.
Many years previous they added
-zmuldefs
to their build to get rid of multiply defined symbol errors. The compiler emits code for running constructors/destructors on global objects.-zmuldefs
forces them to live at the same location in memory but it still runs the constructors/destructors once for the exe and each library that included the offending header -- hence the double-free.