mirror of
https://github.com/abseil/abseil-cpp.git
synced 2026-06-04 12:07:05 +08:00
PR #1500: Define MAP_ANONYMOUS if not defined
Included are additional automated edits by clang-format on import. Merged74896699finto22091f4c0dMerging this change closes #1500 COPYBARA_INTEGRATE_REVIEW=https://github.com/abseil/abseil-cpp/pull/1500 from ryandesign:MAP_ANONYMOUSd74896699fPiperOrigin-RevId: 552922776 Change-Id: I96a0395cb5e7156d7c7a889491c5d0b4cf755819
This commit is contained in:
committed by
Copybara-Service
parent
c66815ac2e
commit
5b3b0ed81c
@@ -47,24 +47,20 @@
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <cerrno>
|
||||
#include <cstddef>
|
||||
#include <new> // for placement-new
|
||||
#include <new> // for placement-new
|
||||
|
||||
#include "absl/base/dynamic_annotations.h"
|
||||
#include "absl/base/internal/raw_logging.h"
|
||||
#include "absl/base/internal/spinlock.h"
|
||||
|
||||
// MAP_ANONYMOUS
|
||||
#if defined(__APPLE__) || defined(__hexagon__)
|
||||
// For mmap, Linux defines both MAP_ANONYMOUS and MAP_ANON and says MAP_ANON is
|
||||
// deprecated. In Darwin, MAP_ANON is all there is.
|
||||
#if !defined MAP_ANONYMOUS
|
||||
#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
|
||||
#define MAP_ANONYMOUS MAP_ANON
|
||||
#endif // !MAP_ANONYMOUS
|
||||
#endif // __APPLE__
|
||||
#endif
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
@@ -126,7 +122,7 @@ static int IntLog2(size_t size, size_t base) {
|
||||
static int Random(uint32_t *state) {
|
||||
uint32_t r = *state;
|
||||
int result = 1;
|
||||
while ((((r = r*1103515245 + 12345) >> 30) & 1) == 0) {
|
||||
while ((((r = r * 1103515245 + 12345) >> 30) & 1) == 0) {
|
||||
result++;
|
||||
}
|
||||
*state = r;
|
||||
@@ -148,7 +144,7 @@ static int LLA_SkiplistLevels(size_t size, size_t base, uint32_t *random) {
|
||||
size_t max_fit = (size - offsetof(AllocList, next)) / sizeof(AllocList *);
|
||||
int level = IntLog2(size, base) + (random != nullptr ? Random(random) : 1);
|
||||
if (static_cast<size_t>(level) > max_fit) level = static_cast<int>(max_fit);
|
||||
if (level > kMaxLevel-1) level = kMaxLevel - 1;
|
||||
if (level > kMaxLevel - 1) level = kMaxLevel - 1;
|
||||
ABSL_RAW_CHECK(level >= 1, "block not big enough for even one level");
|
||||
return level;
|
||||
}
|
||||
@@ -157,8 +153,8 @@ static int LLA_SkiplistLevels(size_t size, size_t base, uint32_t *random) {
|
||||
// For 0 <= i < head->levels, set prev[i] to "no_greater", where no_greater
|
||||
// points to the last element at level i in the AllocList less than *e, or is
|
||||
// head if no such element exists.
|
||||
static AllocList *LLA_SkiplistSearch(AllocList *head,
|
||||
AllocList *e, AllocList **prev) {
|
||||
static AllocList *LLA_SkiplistSearch(AllocList *head, AllocList *e,
|
||||
AllocList **prev) {
|
||||
AllocList *p = head;
|
||||
for (int level = head->levels - 1; level >= 0; level--) {
|
||||
for (AllocList *n; (n = p->next[level]) != nullptr && n < e; p = n) {
|
||||
@@ -194,7 +190,7 @@ static void LLA_SkiplistDelete(AllocList *head, AllocList *e,
|
||||
prev[i]->next[i] = e->next[i];
|
||||
}
|
||||
while (head->levels > 0 && head->next[head->levels - 1] == nullptr) {
|
||||
head->levels--; // reduce head->levels if level unused
|
||||
head->levels--; // reduce head->levels if level unused
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,9 +249,9 @@ void CreateGlobalArenas() {
|
||||
|
||||
// Returns a global arena that does not call into hooks. Used by NewArena()
|
||||
// when kCallMallocHook is not set.
|
||||
LowLevelAlloc::Arena* UnhookedArena() {
|
||||
LowLevelAlloc::Arena *UnhookedArena() {
|
||||
base_internal::LowLevelCallOnce(&create_globals_once, CreateGlobalArenas);
|
||||
return reinterpret_cast<LowLevelAlloc::Arena*>(&unhooked_arena_storage);
|
||||
return reinterpret_cast<LowLevelAlloc::Arena *>(&unhooked_arena_storage);
|
||||
}
|
||||
|
||||
#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING
|
||||
@@ -273,7 +269,7 @@ LowLevelAlloc::Arena *UnhookedAsyncSigSafeArena() {
|
||||
// Returns the default arena, as used by LowLevelAlloc::Alloc() and friends.
|
||||
LowLevelAlloc::Arena *LowLevelAlloc::DefaultArena() {
|
||||
base_internal::LowLevelCallOnce(&create_globals_once, CreateGlobalArenas);
|
||||
return reinterpret_cast<LowLevelAlloc::Arena*>(&default_arena_storage);
|
||||
return reinterpret_cast<LowLevelAlloc::Arena *>(&default_arena_storage);
|
||||
}
|
||||
|
||||
// magic numbers to identify allocated and unallocated blocks
|
||||
@@ -360,8 +356,7 @@ LowLevelAlloc::Arena::Arena(uint32_t flags_value)
|
||||
min_size(2 * round_up),
|
||||
random(0) {
|
||||
freelist.header.size = 0;
|
||||
freelist.header.magic =
|
||||
Magic(kMagicUnallocated, &freelist.header);
|
||||
freelist.header.magic = Magic(kMagicUnallocated, &freelist.header);
|
||||
freelist.header.arena = this;
|
||||
freelist.levels = 0;
|
||||
memset(freelist.next, 0, sizeof(freelist.next));
|
||||
@@ -379,7 +374,7 @@ LowLevelAlloc::Arena *LowLevelAlloc::NewArena(uint32_t flags) {
|
||||
meta_data_arena = UnhookedArena();
|
||||
}
|
||||
Arena *result =
|
||||
new (AllocWithArena(sizeof (*result), meta_data_arena)) Arena(flags);
|
||||
new (AllocWithArena(sizeof(*result), meta_data_arena)) Arena(flags);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -484,8 +479,8 @@ static void Coalesce(AllocList *a) {
|
||||
AllocList *prev[kMaxLevel];
|
||||
LLA_SkiplistDelete(&arena->freelist, n, prev);
|
||||
LLA_SkiplistDelete(&arena->freelist, a, prev);
|
||||
a->levels = LLA_SkiplistLevels(a->header.size, arena->min_size,
|
||||
&arena->random);
|
||||
a->levels =
|
||||
LLA_SkiplistLevels(a->header.size, arena->min_size, &arena->random);
|
||||
LLA_SkiplistInsert(&arena->freelist, a, prev);
|
||||
}
|
||||
}
|
||||
@@ -493,27 +488,27 @@ static void Coalesce(AllocList *a) {
|
||||
// Adds block at location "v" to the free list
|
||||
// L >= arena->mu
|
||||
static void AddToFreelist(void *v, LowLevelAlloc::Arena *arena) {
|
||||
AllocList *f = reinterpret_cast<AllocList *>(
|
||||
reinterpret_cast<char *>(v) - sizeof (f->header));
|
||||
AllocList *f = reinterpret_cast<AllocList *>(reinterpret_cast<char *>(v) -
|
||||
sizeof(f->header));
|
||||
ABSL_RAW_CHECK(f->header.magic == Magic(kMagicAllocated, &f->header),
|
||||
"bad magic number in AddToFreelist()");
|
||||
ABSL_RAW_CHECK(f->header.arena == arena,
|
||||
"bad arena pointer in AddToFreelist()");
|
||||
f->levels = LLA_SkiplistLevels(f->header.size, arena->min_size,
|
||||
&arena->random);
|
||||
f->levels =
|
||||
LLA_SkiplistLevels(f->header.size, arena->min_size, &arena->random);
|
||||
AllocList *prev[kMaxLevel];
|
||||
LLA_SkiplistInsert(&arena->freelist, f, prev);
|
||||
f->header.magic = Magic(kMagicUnallocated, &f->header);
|
||||
Coalesce(f); // maybe coalesce with successor
|
||||
Coalesce(prev[0]); // maybe coalesce with predecessor
|
||||
Coalesce(f); // maybe coalesce with successor
|
||||
Coalesce(prev[0]); // maybe coalesce with predecessor
|
||||
}
|
||||
|
||||
// Frees storage allocated by LowLevelAlloc::Alloc().
|
||||
// L < arena->mu
|
||||
void LowLevelAlloc::Free(void *v) {
|
||||
if (v != nullptr) {
|
||||
AllocList *f = reinterpret_cast<AllocList *>(
|
||||
reinterpret_cast<char *>(v) - sizeof (f->header));
|
||||
AllocList *f = reinterpret_cast<AllocList *>(reinterpret_cast<char *>(v) -
|
||||
sizeof(f->header));
|
||||
LowLevelAlloc::Arena *arena = f->header.arena;
|
||||
ArenaLock section(arena);
|
||||
AddToFreelist(v, arena);
|
||||
@@ -528,21 +523,21 @@ void LowLevelAlloc::Free(void *v) {
|
||||
static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) {
|
||||
void *result = nullptr;
|
||||
if (request != 0) {
|
||||
AllocList *s; // will point to region that satisfies request
|
||||
AllocList *s; // will point to region that satisfies request
|
||||
ArenaLock section(arena);
|
||||
// round up with header
|
||||
size_t req_rnd = RoundUp(CheckedAdd(request, sizeof (s->header)),
|
||||
arena->round_up);
|
||||
for (;;) { // loop until we find a suitable region
|
||||
size_t req_rnd =
|
||||
RoundUp(CheckedAdd(request, sizeof(s->header)), arena->round_up);
|
||||
for (;;) { // loop until we find a suitable region
|
||||
// find the minimum levels that a block of this size must have
|
||||
int i = LLA_SkiplistLevels(req_rnd, arena->min_size, nullptr) - 1;
|
||||
if (i < arena->freelist.levels) { // potential blocks exist
|
||||
if (i < arena->freelist.levels) { // potential blocks exist
|
||||
AllocList *before = &arena->freelist; // predecessor of s
|
||||
while ((s = Next(i, before, arena)) != nullptr &&
|
||||
s->header.size < req_rnd) {
|
||||
before = s;
|
||||
}
|
||||
if (s != nullptr) { // we found a region
|
||||
if (s != nullptr) { // we found a region
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -596,12 +591,12 @@ static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) {
|
||||
AddToFreelist(&s->levels, arena); // insert new region into free list
|
||||
}
|
||||
AllocList *prev[kMaxLevel];
|
||||
LLA_SkiplistDelete(&arena->freelist, s, prev); // remove from free list
|
||||
LLA_SkiplistDelete(&arena->freelist, s, prev); // remove from free list
|
||||
// s points to the first free region that's big enough
|
||||
if (CheckedAdd(req_rnd, arena->min_size) <= s->header.size) {
|
||||
// big enough to split
|
||||
AllocList *n = reinterpret_cast<AllocList *>
|
||||
(req_rnd + reinterpret_cast<char *>(s));
|
||||
AllocList *n =
|
||||
reinterpret_cast<AllocList *>(req_rnd + reinterpret_cast<char *>(s));
|
||||
n->header.size = s->header.size - req_rnd;
|
||||
n->header.magic = Magic(kMagicAllocated, &n->header);
|
||||
n->header.arena = arena;
|
||||
|
||||
@@ -31,6 +31,9 @@
|
||||
|
||||
#ifdef ABSL_HAVE_MMAP
|
||||
#include <sys/mman.h>
|
||||
#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
|
||||
#define MAP_ANONYMOUS MAP_ANON
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
@@ -81,10 +84,10 @@ struct FailureSignalData {
|
||||
struct sigaction previous_action;
|
||||
// StructSigaction is used to silence -Wmissing-field-initializers.
|
||||
using StructSigaction = struct sigaction;
|
||||
#define FSD_PREVIOUS_INIT FailureSignalData::StructSigaction()
|
||||
#define FSD_PREVIOUS_INIT FailureSignalData::StructSigaction()
|
||||
#else
|
||||
void (*previous_handler)(int);
|
||||
#define FSD_PREVIOUS_INIT SIG_DFL
|
||||
#define FSD_PREVIOUS_INIT SIG_DFL
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -136,7 +139,7 @@ const char* FailureSignalToString(int signo) {
|
||||
#ifdef ABSL_HAVE_SIGALTSTACK
|
||||
|
||||
static bool SetupAlternateStackOnce() {
|
||||
#if defined(__wasm__) || defined (__asjms__)
|
||||
#if defined(__wasm__) || defined(__asjms__)
|
||||
const size_t page_mask = getpagesize() - 1;
|
||||
#else
|
||||
const size_t page_mask = static_cast<size_t>(sysconf(_SC_PAGESIZE)) - 1;
|
||||
@@ -157,9 +160,6 @@ static bool SetupAlternateStackOnce() {
|
||||
#ifdef ABSL_HAVE_MMAP
|
||||
#ifndef MAP_STACK
|
||||
#define MAP_STACK 0
|
||||
#endif
|
||||
#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
|
||||
#define MAP_ANONYMOUS MAP_ANON
|
||||
#endif
|
||||
sigstk.ss_sp = mmap(nullptr, sigstk.ss_size, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
|
||||
@@ -248,7 +248,7 @@ static void WriteSignalMessage(int signo, int cpu,
|
||||
if (signal_string != nullptr && signal_string[0] != '\0') {
|
||||
snprintf(buf, sizeof(buf), "*** %s received at time=%ld%s ***\n",
|
||||
signal_string,
|
||||
static_cast<long>(time(nullptr)), // NOLINT(runtime/int)
|
||||
static_cast<long>(time(nullptr)), // NOLINT(runtime/int)
|
||||
on_cpu);
|
||||
} else {
|
||||
snprintf(buf, sizeof(buf), "*** Signal %d received at time=%ld%s ***\n",
|
||||
@@ -311,7 +311,8 @@ static void PortableSleepForSeconds(int seconds) {
|
||||
struct timespec sleep_time;
|
||||
sleep_time.tv_sec = seconds;
|
||||
sleep_time.tv_nsec = 0;
|
||||
while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR) {}
|
||||
while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR) {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -321,9 +322,7 @@ static void PortableSleepForSeconds(int seconds) {
|
||||
// set amount of time. If AbslFailureSignalHandler() hangs for more than
|
||||
// the alarm timeout, ImmediateAbortSignalHandler() will abort the
|
||||
// program.
|
||||
static void ImmediateAbortSignalHandler(int) {
|
||||
RaiseToDefaultHandler(SIGABRT);
|
||||
}
|
||||
static void ImmediateAbortSignalHandler(int) { RaiseToDefaultHandler(SIGABRT); }
|
||||
#endif
|
||||
|
||||
// absl::base_internal::GetTID() returns pid_t on most platforms, but
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
|
||||
#ifdef ABSL_HAVE_MMAP
|
||||
#include <sys/mman.h>
|
||||
#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
|
||||
#define MAP_ANONYMOUS MAP_ANON
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
|
||||
@@ -18,14 +18,17 @@
|
||||
#ifdef ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION
|
||||
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/internal/raw_logging.h"
|
||||
|
||||
#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
|
||||
#define MAP_ANONYMOUS MAP_ANON
|
||||
#endif
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace debugging_internal {
|
||||
|
||||
@@ -40,6 +40,10 @@
|
||||
#include "absl/memory/memory.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
|
||||
#define MAP_ANONYMOUS MAP_ANON
|
||||
#endif
|
||||
|
||||
using testing::Contains;
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -86,21 +90,13 @@ int ABSL_ATTRIBUTE_SECTION_VARIABLE(.text.unlikely) unlikely_func() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ABSL_ATTRIBUTE_SECTION_VARIABLE(.text.hot) hot_func() {
|
||||
return 0;
|
||||
}
|
||||
int ABSL_ATTRIBUTE_SECTION_VARIABLE(.text.hot) hot_func() { return 0; }
|
||||
|
||||
int ABSL_ATTRIBUTE_SECTION_VARIABLE(.text.startup) startup_func() {
|
||||
return 0;
|
||||
}
|
||||
int ABSL_ATTRIBUTE_SECTION_VARIABLE(.text.startup) startup_func() { return 0; }
|
||||
|
||||
int ABSL_ATTRIBUTE_SECTION_VARIABLE(.text.exit) exit_func() {
|
||||
return 0;
|
||||
}
|
||||
int ABSL_ATTRIBUTE_SECTION_VARIABLE(.text.exit) exit_func() { return 0; }
|
||||
|
||||
int /*ABSL_ATTRIBUTE_SECTION_VARIABLE(.text)*/ regular_func() {
|
||||
return 0;
|
||||
}
|
||||
int /*ABSL_ATTRIBUTE_SECTION_VARIABLE(.text)*/ regular_func() { return 0; }
|
||||
|
||||
// Thread-local data may confuse the symbolizer, ensure that it does not.
|
||||
// Variable sizes and order are important.
|
||||
@@ -121,7 +117,7 @@ static volatile bool volatile_bool = false;
|
||||
// Force the binary to be large enough that a THP .text remap will succeed.
|
||||
static constexpr size_t kHpageSize = 1 << 21;
|
||||
const char kHpageTextPadding[kHpageSize * 4] ABSL_ATTRIBUTE_SECTION_VARIABLE(
|
||||
.text) = "";
|
||||
.text) = "";
|
||||
|
||||
#else
|
||||
static void *GetPCFromFnPtr(void *ptr) {
|
||||
@@ -313,10 +309,8 @@ TEST(Symbolize, SymbolizeWithDemanglingStackConsumption) {
|
||||
const size_t kPageSize = 64 << 10;
|
||||
// We place a read-only symbols into the .text section and verify that we can
|
||||
// symbolize them and other symbols after remapping them.
|
||||
const char kPadding0[kPageSize * 4] ABSL_ATTRIBUTE_SECTION_VARIABLE(.text) =
|
||||
"";
|
||||
const char kPadding1[kPageSize * 4] ABSL_ATTRIBUTE_SECTION_VARIABLE(.text) =
|
||||
"";
|
||||
const char kPadding0[kPageSize * 4] ABSL_ATTRIBUTE_SECTION_VARIABLE(.text) = "";
|
||||
const char kPadding1[kPageSize * 4] ABSL_ATTRIBUTE_SECTION_VARIABLE(.text) = "";
|
||||
|
||||
static int FilterElfHeader(struct dl_phdr_info *info, size_t size, void *data) {
|
||||
for (int i = 0; i < info->dlpi_phnum; i++) {
|
||||
@@ -474,9 +468,9 @@ extern "C" {
|
||||
inline void *ABSL_ATTRIBUTE_ALWAYS_INLINE inline_func() {
|
||||
void *pc = nullptr;
|
||||
#if defined(__i386__)
|
||||
__asm__ __volatile__("call 1f;\n 1: pop %[PC]" : [ PC ] "=r"(pc));
|
||||
__asm__ __volatile__("call 1f;\n 1: pop %[PC]" : [PC] "=r"(pc));
|
||||
#elif defined(__x86_64__)
|
||||
__asm__ __volatile__("leaq 0(%%rip),%[PC];\n" : [ PC ] "=r"(pc));
|
||||
__asm__ __volatile__("leaq 0(%%rip),%[PC];\n" : [PC] "=r"(pc));
|
||||
#endif
|
||||
return pc;
|
||||
}
|
||||
@@ -484,9 +478,9 @@ inline void *ABSL_ATTRIBUTE_ALWAYS_INLINE inline_func() {
|
||||
void *ABSL_ATTRIBUTE_NOINLINE non_inline_func() {
|
||||
void *pc = nullptr;
|
||||
#if defined(__i386__)
|
||||
__asm__ __volatile__("call 1f;\n 1: pop %[PC]" : [ PC ] "=r"(pc));
|
||||
__asm__ __volatile__("call 1f;\n 1: pop %[PC]" : [PC] "=r"(pc));
|
||||
#elif defined(__x86_64__)
|
||||
__asm__ __volatile__("leaq 0(%%rip),%[PC];\n" : [ PC ] "=r"(pc));
|
||||
__asm__ __volatile__("leaq 0(%%rip),%[PC];\n" : [PC] "=r"(pc));
|
||||
#endif
|
||||
return pc;
|
||||
}
|
||||
@@ -601,7 +595,7 @@ TEST(Symbolize, SymbolizeWithDemangling) {
|
||||
}
|
||||
|
||||
#endif // !defined(ABSL_CONSUME_DLL)
|
||||
#else // Symbolizer unimplemented
|
||||
#else // Symbolizer unimplemented
|
||||
TEST(Symbolize, Unimplemented) {
|
||||
char buf[64];
|
||||
EXPECT_FALSE(absl::Symbolize((void *)(&nonstatic_func), buf, sizeof(buf)));
|
||||
|
||||
Reference in New Issue
Block a user