From dbe26fdcc7de503539837467299b96c4a93084cc Mon Sep 17 00:00:00 2001 From: Dmitriy Ivanov Date: Mon, 4 May 2015 19:30:49 -0700 Subject: [PATCH] Fix protected symbol lookups for mips Bug: http://b/20694161 Change-Id: I5cc58034f9776e1db9cddc34abe48ef85f6048f4 --- libc/include/elf.h | 5 +++++ linker/linker_mips.cpp | 26 ++++++++++++++++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/libc/include/elf.h b/libc/include/elf.h index df768ba52..dcf01abc5 100644 --- a/libc/include/elf.h +++ b/libc/include/elf.h @@ -187,6 +187,11 @@ typedef struct { #define STT_LOPROC 13 #define STT_HIPROC 15 +#define STV_DEFAULT 0 +#define STV_INTERNAL 1 +#define STV_HIDDEN 2 +#define STV_PROTECTED 3 + /* The kernel uses NT_PRFPREG but glibc also offers NT_FPREGSET */ #define NT_FPREGSET NT_PRFPREG diff --git a/linker/linker_mips.cpp b/linker/linker_mips.cpp index 7436180c3..a7a4bc064 100644 --- a/linker/linker_mips.cpp +++ b/linker/linker_mips.cpp @@ -157,20 +157,34 @@ bool soinfo::mips_relocate_got(const VersionTracker& version_tracker, soinfo* lsi = nullptr; const ElfW(Sym)* s = nullptr; - const version_info* vi = nullptr; + ElfW(Word) st_visibility = (local_sym->st_other & 0x3); - if (!lookup_version_info(version_tracker, sym, sym_name, &vi)) { - return false; - } + if (st_visibility == STV_DEFAULT) { + const version_info* vi = nullptr; + + if (!lookup_version_info(version_tracker, sym, sym_name, &vi)) { + return false; + } - if (!soinfo_do_lookup(this, sym_name, vi, &lsi, global_group, local_group, &s)) { + if (!soinfo_do_lookup(this, sym_name, vi, &lsi, global_group, local_group, &s)) { + return false; + } + } else if (st_visibility == STV_PROTECTED) { + if (local_sym->st_value == 0) { + DL_ERR("%s: invalid symbol \"%s\" (PROTECTED/UNDEFINED) ", get_soname(), sym_name); + return false; + } + s = local_sym; + lsi = this; + } else { + DL_ERR("%s: invalid symbol \"%s\" visibility: 0x%x", get_soname(), sym_name, st_visibility); return false; } if (s == nullptr) { // We only allow an undefined symbol if this is a weak reference. if (ELF_ST_BIND(local_sym->st_info) != STB_WEAK) { - DL_ERR("cannot locate \"%s\"...", sym_name); + DL_ERR("%s: cannot locate \"%s\"...", get_soname(), sym_name); return false; } *got = 0; -- 2.11.0