Commit bf655de0 by Abseil Team Committed by Gennadiy Rozental

Export of internal Abseil changes

--
13b7cb0eff8fda5127193e11dbe0b8655415b512 by Gennadiy Rozental <rogeeff@google.com>:

Change the preprocessor guards to properly exclude tests which does not build on older
version on libstdc++.

Fixes #731

PiperOrigin-RevId: 319987618

--
ab2155855b4dd1259a3dd9f48fbb5e6e8c2ccd3f by Derek Mauro <dmauro@google.com>:

Update clang-latest container to LLVM 052e1e0cfd9, Bazel 3.3.1, and CMake 3.17.3

PiperOrigin-RevId: 319835484

--
7554283733c309649a05b7f1891b2593e50f07b7 by Abseil Team <absl-team@google.com>:

Implement support for LOAD segments that don't start at p_vaddr==0.

PiperOrigin-RevId: 319694669
GitOrigin-RevId: 13b7cb0eff8fda5127193e11dbe0b8655415b512
Change-Id: I220c2af4169cf8e4dad20cb372589ec7def0e018
parent 38db52ad
......@@ -2463,9 +2463,12 @@ TEST(Btree,
EXPECT_THAT(s2, ElementsAre(IsEmpty(), ElementsAre(IsNull())));
}
// GCC 4.9 has a bug in the std::pair constructors that prevents explicit
// conversions between pair types.
#if defined(__clang__) || !defined(__GNUC__) || __GNUC__ >= 5
// libstdc++ included with GCC 4.9 has a bug in the std::pair constructors that
// prevents explicit conversions between pair types.
// We only run this test for the libstdc++ from GCC 7 or newer because we can't
// reliably check the libstdc++ version prior to that release.
#if !defined(__GLIBCXX__) || \
(defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 7)
TEST(Btree, MapRangeConstructorAndInsertSupportExplicitConversionComparable) {
const std::pair<absl::string_view, int> names[] = {{"n1", 1}, {"n2", 2}};
......
......@@ -57,6 +57,7 @@
#include <unistd.h>
#include <algorithm>
#include <array>
#include <atomic>
#include <cerrno>
#include <cinttypes>
......@@ -184,6 +185,7 @@ struct ObjFile {
fd(-1),
elf_type(-1) {
SafeMemZero(&elf_header, sizeof(elf_header));
SafeMemZero(&phdr[0], sizeof(phdr));
}
char *filename;
......@@ -196,6 +198,10 @@ struct ObjFile {
int fd;
int elf_type;
ElfW(Ehdr) elf_header;
// PT_LOAD program header describing executable code.
// Normally we expect just one, but SWIFT binaries have two.
std::array<ElfW(Phdr), 2> phdr;
};
// Build 4-way associative cache for symbols. Within each cache line, symbols
......@@ -1272,6 +1278,36 @@ static bool MaybeInitializeObjFile(ObjFile *obj) {
ABSL_RAW_LOG(WARNING, "%s: failed to read elf header", obj->filename);
return false;
}
const int phnum = obj->elf_header.e_phnum;
const int phentsize = obj->elf_header.e_phentsize;
size_t phoff = obj->elf_header.e_phoff;
int num_executable_load_segments = 0;
for (int j = 0; j < phnum; j++) {
ElfW(Phdr) phdr;
if (!ReadFromOffsetExact(obj->fd, &phdr, sizeof(phdr), phoff)) {
ABSL_RAW_LOG(WARNING, "%s: failed to read program header %d",
obj->filename, j);
return false;
}
phoff += phentsize;
constexpr int rx = PF_X | PF_R;
if (phdr.p_type != PT_LOAD || (phdr.p_flags & rx) != rx) {
// Not a LOAD segment, or not executable code.
continue;
}
if (num_executable_load_segments < obj->phdr.size()) {
memcpy(&obj->phdr[num_executable_load_segments++], &phdr, sizeof(phdr));
} else {
ABSL_RAW_LOG(WARNING, "%s: too many executable LOAD segments",
obj->filename);
break;
}
}
if (num_executable_load_segments == 0) {
// This object has no "r-x" LOAD segments. That's unexpected.
ABSL_RAW_LOG(WARNING, "%s: no executable LOAD segments", obj->filename);
return false;
}
}
return true;
}
......@@ -1295,17 +1331,45 @@ const char *Symbolizer::GetSymbol(const void *const pc) {
int fd = -1;
if (obj != nullptr) {
if (MaybeInitializeObjFile(obj)) {
if (obj->elf_type == ET_DYN &&
reinterpret_cast<uint64_t>(obj->start_addr) >= obj->offset) {
const size_t start_addr = reinterpret_cast<size_t>(obj->start_addr);
if (obj->elf_type == ET_DYN && start_addr >= obj->offset) {
// This object was relocated.
//
// For obj->offset > 0, adjust the relocation since a mapping at offset
// X in the file will have a start address of [true relocation]+X.
relocation = reinterpret_cast<ptrdiff_t>(obj->start_addr) - obj->offset;
relocation = start_addr - obj->offset;
// Note: some binaries have multiple "rx" LOAD segments. We must
// find the right one.
ElfW(Phdr) *phdr = nullptr;
for (int j = 0; j < obj->phdr.size(); j++) {
ElfW(Phdr) &p = obj->phdr[j];
if (p.p_type != PT_LOAD) {
// We only expect PT_LOADs. This must be PT_NULL that we didn't
// write over (i.e. we exhausted all interesting PT_LOADs).
ABSL_RAW_CHECK(p.p_type == PT_NULL, "unexpected p_type");
break;
}
if (pc < reinterpret_cast<void *>(start_addr + p.p_memsz)) {
phdr = &p;
break;
}
}
if (phdr == nullptr) {
// That's unexpected. Hope for the best.
ABSL_RAW_LOG(
WARNING,
"%s: unable to find LOAD segment for pc: %p, start_addr: %zx",
obj->filename, pc, start_addr);
} else {
// Adjust relocation in case phdr.p_vaddr != 0.
// This happens for binaries linked with `lld --rosegment`, and for
// binaries linked with BFD `ld -z separate-code`.
relocation -= phdr->p_vaddr - phdr->p_offset;
}
}
fd = obj->fd;
}
if (GetSymbolFromObjectFile(*obj, pc, relocation, symbol_buf_,
sizeof(symbol_buf_), tmp_buf_,
sizeof(tmp_buf_)) == SYMBOL_FOUND) {
......@@ -1313,6 +1377,7 @@ const char *Symbolizer::GetSymbol(const void *const pc) {
DemangleInplace(symbol_buf_, sizeof(symbol_buf_), tmp_buf_,
sizeof(tmp_buf_));
}
}
} else {
#if ABSL_HAVE_VDSO_SUPPORT
VDSOSupport vdso;
......
......@@ -16,6 +16,6 @@
# Test scripts should source this file to get the identifiers.
readonly LINUX_ALPINE_CONTAINER="gcr.io/google.com/absl-177019/alpine:20191016"
readonly LINUX_CLANG_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20200401"
readonly LINUX_CLANG_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20200706"
readonly LINUX_GCC_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-latest:20200319"
readonly LINUX_GCC_49_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-4.9:20191018"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment