[PATCH] ELF: improve recognition of objects asking for on-load resolution

57 views
Skip to first unread message

Nadav Har'El

unread,
May 9, 2018, 9:05:33 AM5/9/18
to osv...@googlegroups.com, Nadav Har'El
By default, we do lazy function call resolutions - functions are only looked
up on first use. But a shared object may ask (for various reasons) to do
all the resolutions up-front when the object is loaded. This is marked by
creating this object with the "-z now" linker option.

There are several standard ways a linker can use to mark this option in
the ELF file, though. The only method I encountered in the past was the
inclusion of a DT_BIND_NOW dynamic tag. However, it now appears that
some newer linkers do not do this, and instead put the bit DF_BIND_NOW
in the DT_FLAGS tag. Some documents claim that the DT_BIND_NOW tag is
obsolete. Also, some Linux linkers also put the DF_1_NOW flag in the
DT_FLAGS_1 tag, which was originally the Solaris-only way of marking this.

This patch adds support for all these alternative tags and flags. If any
one of those appears on the shared object, it is treated as bind-now.

Fixes #967.

Signed-off-by: Nadav Har'El <n...@scylladb.com>
---
include/osv/elf.hh | 9 +++++++++
core/elf.cc | 4 +++-
2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/include/osv/elf.hh b/include/osv/elf.hh
index e0966c40..304021af 100644
--- a/include/osv/elf.hh
+++ b/include/osv/elf.hh
@@ -189,6 +189,8 @@ enum {
DT_FINI_ARRAY = 26, // d_ptr Pointer to an array of pointers to termination functions.
DT_INIT_ARRAYSZ = 27, // d_val Size, in bytes, of the array of initialization functions.
DT_FINI_ARRAYSZ = 28, // d_val Size, in bytes, of the array of termination functions.
+ DT_FLAGS = 28, // value is various flags, bits from DF_*.
+ DT_FLAGS_1 = 0x6ffffffb, // value is various flags, bits from DF_1_*.
DT_LOOS = 0x60000000, // Defines a range of dynamic table tags that are reserved for
// environment-specific use.
DT_HIOS = 0x6FFFFFFF, //
@@ -198,6 +200,13 @@ enum {
DT_GNU_HASH = 0x6ffffef5,
};

+enum {
+ DF_BIND_NOW = 0x8,
+};
+enum {
+ DF_1_NOW = 0x1,
+};
+
enum {
STN_UNDEF = 0,
};
diff --git a/core/elf.cc b/core/elf.cc
index ca77ae77..4f064cb6 100644
--- a/core/elf.cc
+++ b/core/elf.cc
@@ -630,7 +630,9 @@ void object::relocate_pltgot()
#endif /* AARCH64_PORT_STUB */
original_plt = static_cast<void*>(_base + (u64)pltgot[1]);
}
- bool bind_now = dynamic_exists(DT_BIND_NOW) || mlocked();
+ bool bind_now = dynamic_exists(DT_BIND_NOW) || mlocked() ||
+ (dynamic_exists(DT_FLAGS) && (dynamic_val(DT_FLAGS) & DF_BIND_NOW)) ||
+ (dynamic_exists(DT_FLAGS_1) && (dynamic_val(DT_FLAGS_1) & DF_1_NOW));

auto rel = dynamic_ptr<Elf64_Rela>(DT_JMPREL);
auto nrel = dynamic_val(DT_PLTRELSZ) / sizeof(*rel);
--
2.14.3

Commit Bot

unread,
May 9, 2018, 12:20:22 PM5/9/18
to osv...@googlegroups.com, Nadav Har'El
From: Nadav Har'El <n...@scylladb.com>
Committer: Nadav Har'El <n...@scylladb.com>
Branch: master

ELF: improve recognition of objects asking for on-load resolution

By default, we do lazy function call resolutions - functions are only looked
up on first use. But a shared object may ask (for various reasons) to do
all the resolutions up-front when the object is loaded. This is marked by
creating this object with the "-z now" linker option.

There are several standard ways a linker can use to mark this option in
the ELF file, though. The only method I encountered in the past was the
inclusion of a DT_BIND_NOW dynamic tag. However, it now appears that
some newer linkers do not do this, and instead put the bit DF_BIND_NOW
in the DT_FLAGS tag. Some documents claim that the DT_BIND_NOW tag is
obsolete. Also, some Linux linkers also put the DF_1_NOW flag in the
DT_FLAGS_1 tag, which was originally the Solaris-only way of marking this.

This patch adds support for all these alternative tags and flags. If any
one of those appears on the shared object, it is treated as bind-now.

Fixes #967.

Signed-off-by: Nadav Har'El <n...@scylladb.com>
Message-Id: <2018050913052...@scylladb.com>

---
diff --git a/core/elf.cc b/core/elf.cc
--- a/core/elf.cc
+++ b/core/elf.cc
@@ -630,7 +630,9 @@ void object::relocate_pltgot()
#endif /* AARCH64_PORT_STUB */
original_plt = static_cast<void*>(_base + (u64)pltgot[1]);
}
- bool bind_now = dynamic_exists(DT_BIND_NOW) || mlocked();
+ bool bind_now = dynamic_exists(DT_BIND_NOW) || mlocked() ||
+ (dynamic_exists(DT_FLAGS) && (dynamic_val(DT_FLAGS) &
DF_BIND_NOW)) ||
+ (dynamic_exists(DT_FLAGS_1) && (dynamic_val(DT_FLAGS_1) &
DF_1_NOW));

auto rel = dynamic_ptr<Elf64_Rela>(DT_JMPREL);
auto nrel = dynamic_val(DT_PLTRELSZ) / sizeof(*rel);
diff --git a/include/osv/elf.hh b/include/osv/elf.hh
Reply all
Reply to author
Forward
0 new messages