mirror of
https://github.com/abseil/abseil-cpp.git
synced 2026-06-04 20:14:23 +08:00
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
This commit is contained in:
committed by
Gennadiy Rozental
parent
38db52adb2
commit
bf655de09b
@@ -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,23 +1331,52 @@ 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) {
|
||||
// Only try to demangle the symbol name if it fit into symbol_buf_.
|
||||
DemangleInplace(symbol_buf_, sizeof(symbol_buf_), tmp_buf_,
|
||||
sizeof(tmp_buf_));
|
||||
if (GetSymbolFromObjectFile(*obj, pc, relocation, symbol_buf_,
|
||||
sizeof(symbol_buf_), tmp_buf_,
|
||||
sizeof(tmp_buf_)) == SYMBOL_FOUND) {
|
||||
// Only try to demangle the symbol name if it fit into symbol_buf_.
|
||||
DemangleInplace(symbol_buf_, sizeof(symbol_buf_), tmp_buf_,
|
||||
sizeof(tmp_buf_));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#if ABSL_HAVE_VDSO_SUPPORT
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user