merge(3p/absl): subtree merge of Abseil up to e19260f

... notably, this includes Abseil's own StatusOr type, which
conflicted with our implementation (that was taken from TensorFlow).

Change-Id: Ie7d6764b64055caaeb8dc7b6b9d066291e6b538f
This commit is contained in:
Vincent Ambo 2020-11-21 14:43:54 +01:00
parent cc27324d02
commit 082c006c04
854 changed files with 11260 additions and 5296 deletions

View file

@ -57,6 +57,7 @@
#include <unistd.h>
#include <algorithm>
#include <array>
#include <atomic>
#include <cerrno>
#include <cinttypes>
@ -83,6 +84,12 @@ ABSL_NAMESPACE_BEGIN
static char *argv0_value = nullptr;
void InitializeSymbolizer(const char *argv0) {
#ifdef ABSL_HAVE_VDSO_SUPPORT
// We need to make sure VDSOSupport::Init() is called before any setuid or
// chroot calls, so InitializeSymbolizer() should be called very early in the
// life of a program.
absl::debugging_internal::VDSOSupport::Init();
#endif
if (argv0_value != nullptr) {
free(argv0_value);
argv0_value = nullptr;
@ -178,6 +185,7 @@ struct ObjFile {
fd(-1),
elf_type(-1) {
SafeMemZero(&elf_header, sizeof(elf_header));
SafeMemZero(&phdr[0], sizeof(phdr));
}
char *filename;
@ -190,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
@ -1266,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;
size_t 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;
}
@ -1289,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 (size_t 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
@ -1376,7 +1447,7 @@ int InstallSymbolDecorator(SymbolDecorator decorator, void *arg) {
if (!g_decorators_mu.TryLock()) {
// Someone else is using decorators. Get out.
return false;
return -2;
}
int ret = ticket;
if (g_num_decorators >= kMaxDecorators) {
@ -1455,7 +1526,7 @@ bool GetFileMappingHint(const void **start, const void **end, uint64_t *offset,
bool Symbolize(const void *pc, char *out, int out_size) {
// Symbolization is very slow under tsan.
ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
SAFE_ASSERT(out_size >= 0);
debugging_internal::Symbolizer *s = debugging_internal::AllocateSymbolizer();
const char *name = s->GetSymbol(pc);
@ -1474,9 +1545,16 @@ bool Symbolize(const void *pc, char *out, int out_size) {
}
}
debugging_internal::FreeSymbolizer(s);
ANNOTATE_IGNORE_READS_AND_WRITES_END();
ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END();
return ok;
}
ABSL_NAMESPACE_END
} // namespace absl
extern "C" bool AbslInternalGetFileMappingHint(const void **start,
const void **end, uint64_t *offset,
const char **filename) {
return absl::debugging_internal::GetFileMappingHint(start, end, offset,
filename);
}