在不同的动态加载对象中以不同方式解析符号
Resolving symbols differently in different dynamically loaded objects
阅读 these questions 后,我正在寻找有关如何控制符号解析顺序的更多详细信息。
在我的问题中,我有主要的可执行文件 exec
。 exec
动态 link 到 a.so
和 c.so
。 a.so
动态 link 到 b.so
。 b.so
调用函数 foo
,通常由 c.so
提供,但在本例中也由 exec
提供。 b.so
仅适用于 c.so
对 foo
的实现。
情况图:
exec (foo caller and provider)
| \
a.so |
| |
b.so | (foo caller)
| /
c.so (foo provider)
我只能控制a.so
的compilation/source,我linka.so
到exec
用LD_PRELOAD
.
我想在 exec
中调用 foo
以解析为 exec
的实现,并在 b.so
中调用以解析为 c.so
的实施。这种在不同对象中使用不同符号查找的东西可能吗?
不幸的是,没有办法在每个库级别调整符号解析,因此没有简单的方法来实现这一点。
如果 foo
实际上是在主要可执行文件中实现的(而不仅仅是 copy-relocated ),您无能为力,因为主要可执行文件中的符号在解析过程中获得最高优先级(除非你对 GOT 的最终 hacky runtime-patching 没问题,但你不是。
但是如果
foo
在c.so 中实现
- 你已经够绝望了
您可以执行以下操作:
- 在 a.so 中获取 return 拦截器内的地址(使用
__builtin_return_address
)
- 将其与 b.so 的边界相匹配(可以从
/proc/self/maps
获得)
- 根据结果,进行特殊处理(如果调用者在 b.so)或将调用转发给
RTLD_NEXT
这当然有明显的局限性,例如如果 b.so 从另一个 d.so 调用函数,然后调用 foo
,则将不起作用,但在许多情况下可能就足够了。是的,我已经在实践中看到了这种方法。
阅读 these questions 后,我正在寻找有关如何控制符号解析顺序的更多详细信息。
在我的问题中,我有主要的可执行文件 exec
。 exec
动态 link 到 a.so
和 c.so
。 a.so
动态 link 到 b.so
。 b.so
调用函数 foo
,通常由 c.so
提供,但在本例中也由 exec
提供。 b.so
仅适用于 c.so
对 foo
的实现。
情况图:
exec (foo caller and provider)
| \
a.so |
| |
b.so | (foo caller)
| /
c.so (foo provider)
我只能控制a.so
的compilation/source,我linka.so
到exec
用LD_PRELOAD
.
我想在 exec
中调用 foo
以解析为 exec
的实现,并在 b.so
中调用以解析为 c.so
的实施。这种在不同对象中使用不同符号查找的东西可能吗?
不幸的是,没有办法在每个库级别调整符号解析,因此没有简单的方法来实现这一点。
如果 foo
实际上是在主要可执行文件中实现的(而不仅仅是 copy-relocated ),您无能为力,因为主要可执行文件中的符号在解析过程中获得最高优先级(除非你对 GOT 的最终 hacky runtime-patching 没问题,但你不是。
但是如果
foo
在c.so 中实现
- 你已经够绝望了
您可以执行以下操作:
- 在 a.so 中获取 return 拦截器内的地址(使用
__builtin_return_address
) - 将其与 b.so 的边界相匹配(可以从
/proc/self/maps
获得) - 根据结果,进行特殊处理(如果调用者在 b.so)或将调用转发给
RTLD_NEXT
这当然有明显的局限性,例如如果 b.so 从另一个 d.so 调用函数,然后调用 foo
,则将不起作用,但在许多情况下可能就足够了。是的,我已经在实践中看到了这种方法。