* SUCH DAMAGE.
*/
-#ifndef BIONIC_LIBSTDCPP_INCLUDE_CSTDDEF__
-#define BIONIC_LIBSTDCPP_INCLUDE_CSTDDEF__
+#ifndef __LINKER_GLOBALS_H
+#define __LINKER_GLOBALS_H
-/*
- * Standard C++ Library wrapper around the C stddef.h header file.
- * The following 2 types are also declared in the 'std' namespace:
- * . ptrdiff_t
- * . size_t
- */
+#include <link.h>
#include <stddef.h>
-extern "C++" {
+#include <unordered_map>
+
+#define DL_ERR(fmt, x...) \
+ do { \
+ __libc_format_buffer(linker_get_error_buffer(), linker_get_error_buffer_size(), fmt, ##x); \
+ /* If LD_DEBUG is set high enough, log every dlerror(3) message. */ \
+ LD_LOG(kLogErrors, "%s\n", linker_get_error_buffer()); \
+ } while (false)
+
+#define DL_WARN(fmt, x...) \
+ do { \
+ __libc_format_log(ANDROID_LOG_WARN, "linker", fmt, ##x); \
+ __libc_format_fd(2, "WARNING: linker: "); \
+ __libc_format_fd(2, fmt, ##x); \
+ __libc_format_fd(2, "\n"); \
+ } while (false)
+
++#define DL_ERR_AND_LOG(fmt, x...) \
++ do { \
++ DL_ERR(fmt, x); \
++ PRINT(fmt, x); \
++ } while (false)
++
+constexpr ElfW(Versym) kVersymNotNeeded = 0;
+constexpr ElfW(Versym) kVersymGlobal = 1;
+
+// These values are used to call constructors for .init_array && .preinit_array
+extern int g_argc;
+extern char** g_argv;
+extern char** g_envp;
+
+struct soinfo;
+struct android_namespace_t;
+
+extern android_namespace_t g_default_namespace;
-namespace std {
-using ::ptrdiff_t;
-using ::size_t;
-} // namespace std
+extern std::unordered_map<uintptr_t, soinfo*> g_soinfo_handles_map;
-} // extern C++
+// Error buffer "variable"
+char* linker_get_error_buffer();
+size_t linker_get_error_buffer_size();
-#endif // BIONIC_LIBSTDCPP_INCLUDE_CSTDDEF__
+#endif /* __LINKER_GLOBALS_H */
off64_t range_start;
off64_t range_end;
- return safe_add(&range_start, file_offset_, offset) &&
+ // Only header can be located at the 0 offset... This function called to
+ // check DYNSYM and DYNAMIC sections and phdr/shdr - none of them can be
+ // at offset 0.
+
+ return offset > 0 &&
+ safe_add(&range_start, file_offset_, offset) &&
safe_add(&range_end, range_start, size) &&
- range_start < file_size_ &&
- range_end <= file_size_;
+ (range_start < file_size_) &&
+ (range_end <= file_size_) &&
+ ((offset % alignment) == 0);
}
// Loads the program header table from an ELF file into a read-only private
return false;
}
+ // Make sure dynamic_shdr offset and size matches PT_DYNAMIC phdr
+ size_t pt_dynamic_offset = 0;
+ size_t pt_dynamic_filesz = 0;
+ for (size_t i = 0; i < phdr_num_; ++i) {
+ const ElfW(Phdr)* phdr = &phdr_table_[i];
+ if (phdr->p_type == PT_DYNAMIC) {
+ pt_dynamic_offset = phdr->p_offset;
+ pt_dynamic_filesz = phdr->p_filesz;
+ }
+ }
+
+ if (pt_dynamic_offset != dynamic_shdr->sh_offset) {
+ DL_ERR("\"%s\" .dynamic section has invalid offset: 0x%zx, "
+ "expected to match PT_DYNAMIC offset: 0x%zx",
+ name_.c_str(),
+ static_cast<size_t>(dynamic_shdr->sh_offset),
+ pt_dynamic_offset);
+ return false;
+ }
+
+ if (pt_dynamic_filesz != dynamic_shdr->sh_size) {
+ DL_ERR("\"%s\" .dynamic section has invalid size: 0x%zx, "
+ "expected to match PT_DYNAMIC filesz: 0x%zx",
+ name_.c_str(),
+ static_cast<size_t>(dynamic_shdr->sh_size),
+ pt_dynamic_filesz);
+ return false;
+ }
+
if (dynamic_shdr->sh_link >= shdr_num_) {
- DL_ERR("\"%s\" .dynamic section has invalid sh_link: %d", name_.c_str(), dynamic_shdr->sh_link);
+ DL_ERR_AND_LOG("\"%s\" .dynamic section has invalid sh_link: %d",
+ name_.c_str(),
+ dynamic_shdr->sh_link);
return false;
}