Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions compiler-rt/lib/sanitizer_common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ set(SANITIZER_SOURCES_NOTERMINATION
sanitizer_platform_limits_solaris.cpp
sanitizer_posix.cpp
sanitizer_printf.cpp
sanitizer_procmaps_aix.cpp
sanitizer_procmaps_common.cpp
sanitizer_procmaps_bsd.cpp
sanitizer_procmaps_fuchsia.cpp
Expand Down Expand Up @@ -109,6 +110,7 @@ set(SANITIZER_IMPL_HEADERS
sancov_flags.h
sancov_flags.inc
sanitizer_addrhashmap.h
sanitizer_aix.h
sanitizer_allocator.h
sanitizer_allocator_checks.h
sanitizer_allocator_combined.h
Expand Down
43 changes: 43 additions & 0 deletions compiler-rt/lib/sanitizer_common/sanitizer_aix.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//===-- sanitizer_aix.h -----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file is shared between various sanitizers' runtime libraries and
// provides definitions for AIX-specific functions.
//===----------------------------------------------------------------------===//
#ifndef SANITIZER_AIX_H
#define SANITIZER_AIX_H

#include "sanitizer_platform.h"

#if SANITIZER_AIX
# include "sanitizer_common.h"
# include "sanitizer_posix.h"

struct prmap;
typedef struct prmap prmap_t;

namespace __sanitizer {

struct ProcSelfMapsBuff {
char *data;
uptr mmaped_size;
uptr len;
prmap_t *mapEnd;
};

struct MemoryMappingLayoutData {
ProcSelfMapsBuff proc_self_maps;
const char *current;
};

void ReadProcMaps(ProcSelfMapsBuff *proc_maps);

} // namespace __sanitizer

#endif // SANITIZER_AIX
#endif // SANITIZER_AIX_H
17 changes: 9 additions & 8 deletions compiler-rt/lib/sanitizer_common/sanitizer_procmaps.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@

#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
SANITIZER_APPLE || SANITIZER_SOLARIS || SANITIZER_HAIKU || \
SANITIZER_FUCHSIA

#include "sanitizer_common.h"
#include "sanitizer_internal_defs.h"
#include "sanitizer_fuchsia.h"
#include "sanitizer_linux.h"
#include "sanitizer_mac.h"
#include "sanitizer_mutex.h"
SANITIZER_FUCHSIA || SANITIZER_AIX

# include "sanitizer_aix.h"
# include "sanitizer_common.h"
# include "sanitizer_fuchsia.h"
# include "sanitizer_internal_defs.h"
# include "sanitizer_linux.h"
# include "sanitizer_mac.h"
# include "sanitizer_mutex.h"

namespace __sanitizer {

Expand Down
132 changes: 132 additions & 0 deletions compiler-rt/lib/sanitizer_common/sanitizer_procmaps_aix.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
//===-- sanitizer_procmaps_aix.cpp ----------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Information about the process mappings (AIX-specific parts).
//===----------------------------------------------------------------------===//

#include "sanitizer_platform.h"

#if SANITIZER_AIX
# include <assert.h>
# include <stdio.h>
# include <stdlib.h>
# include <sys/procfs.h>

# include "sanitizer_common.h"
# include "sanitizer_file.h"
# include "sanitizer_procmaps.h"

namespace __sanitizer {

static int qsort_comp(const void *va, const void *vb) {
const prmap_t *a = (const prmap_t *)va;
const prmap_t *b = (const prmap_t *)vb;

if (a->pr_vaddr < b->pr_vaddr)
return -1;

if (a->pr_vaddr > b->pr_vaddr)
return 1;

return 0;
}

static prmap_t *SortProcMapEntries(char *buffer) {
prmap_t *begin = (prmap_t *)buffer;
prmap_t *mapIter = begin;
// The AIX procmap utility detects the end of the array of `prmap`s by finding
// an entry where pr_size and pr_vaddr are both zero.
while (mapIter->pr_size != 0 || mapIter->pr_vaddr != 0) ++mapIter;
prmap_t *end = mapIter;

size_t count = end - begin;
size_t elemSize = sizeof(prmap_t);
qsort(begin, count, elemSize, qsort_comp);

return end;
}

void ReadProcMaps(ProcSelfMapsBuff *proc_maps) {
uptr pid = internal_getpid();
constexpr unsigned BUFFER_SIZE = 128;
char filenameBuf[BUFFER_SIZE] = {};
internal_snprintf(filenameBuf, BUFFER_SIZE, "/proc/%d/map", pid);
if (!ReadFileToBuffer(filenameBuf, &proc_maps->data, &proc_maps->mmaped_size,
&proc_maps->len)) {
proc_maps->data = nullptr;
proc_maps->mmaped_size = 0;
proc_maps->len = 0;
proc_maps->mapEnd = nullptr;
return;
}

proc_maps->mapEnd = SortProcMapEntries(proc_maps->data);
}

bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
if (Error())
return false; // simulate empty maps

const prmap_t *mapIter = (const prmap_t *)data_.current;

if (mapIter >= data_.proc_self_maps.mapEnd)
return false;

// Skip the kernel segment.
if ((mapIter->pr_mflags & MA_TYPE_MASK) == MA_KERNTEXT)
++mapIter;

if (mapIter >= data_.proc_self_maps.mapEnd)
return false;

segment->start = (uptr)mapIter->pr_vaddr;
segment->end = segment->start + mapIter->pr_size;

segment->protection = 0;
uint32_t flags = mapIter->pr_mflags;
if (flags & MA_READ)
segment->protection |= kProtectionRead;
if (flags & MA_WRITE)
segment->protection |= kProtectionWrite;
if (flags & MA_EXEC)
segment->protection |= kProtectionExecute;

uint32_t type = mapIter->pr_mflags & MA_TYPE_MASK;
if (type == MA_SLIBTEXT || type == MA_PLIBDATA)
segment->protection |= kProtectionShared;

if (segment->filename && mapIter->pr_pathoff) {
uptr len;
constexpr unsigned BUFFER_SIZE = 128;
char objPath[BUFFER_SIZE] = {};
// Use path /proc/<pid>/object/<object_id>
// TODO: Pass a separate path from mapIter->pr_pathoff to display to the
// user.
// TODO: Append the archive member name if it exists.
internal_snprintf(objPath, BUFFER_SIZE, "/proc/%d/object/%s",
internal_getpid(), mapIter->pr_mapname);
len = Min((uptr)internal_strlen(objPath), segment->filename_size - 1);
internal_strncpy(segment->filename, objPath, len);
segment->filename[len] = 0;

} else if (segment->filename) {
segment->filename[0] = 0;
}

assert(mapIter->pr_off == 0 && "expect a zero offset into module.");
segment->offset = 0;

++mapIter;
data_.current = (const char *)mapIter;

return true;
}

} // namespace __sanitizer

#endif // SANITIZER_AIX
Loading