Merge ^/head r309519 through r309757.

This commit is contained in:
Dimitry Andric 2016-12-09 20:57:43 +00:00
commit 1bde3b7066
319 changed files with 37619 additions and 34004 deletions

View File

@ -147,6 +147,9 @@ OLD_FILES+=usr/lib/clang/3.9.0/lib/freebsd/libclang_rt.ubsan_standalone_cxx-x86_
OLD_DIRS+=usr/lib/clang/3.9.0/lib/freebsd
OLD_DIRS+=usr/lib/clang/3.9.0/lib
OLD_DIRS+=usr/lib/clang/3.9.0
# 20161205: libproc version bump
OLD_LIBS+=usr/lib/libproc.so.3
OLD_LIBS+=usr/lib32/libproc.so.3
# 20161127: Remove vm_page_cache(9)
OLD_FILES+=usr/share/man/man9/vm_page_cache.9.gz
# 20161124: new clang import which bumps version from 3.8.0 to 3.9.0.

View File

@ -47,11 +47,14 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/capsicum.h>
#include <sys/conf.h>
#include <sys/disklabel.h>
#include <sys/filio.h>
#include <sys/mtio.h>
#include <assert.h>
#include <capsicum_helpers.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
@ -92,6 +95,10 @@ main(int argc __unused, char *argv[])
jcl(argv);
setup();
caph_cache_catpages();
if (cap_enter() == -1 && errno != ENOSYS)
err(1, "unable to enter capability mode");
(void)signal(SIGINFO, siginfo_handler);
(void)signal(SIGINT, terminate);
@ -125,6 +132,8 @@ static void
setup(void)
{
u_int cnt;
cap_rights_t rights;
unsigned long cmds[] = { FIODTYPE, MTIOCTOP };
if (in.name == NULL) {
in.name = "stdin";
@ -133,13 +142,20 @@ setup(void)
in.fd = open(in.name, O_RDONLY, 0);
if (in.fd == -1)
err(1, "%s", in.name);
if (caph_limit_stdin() == -1)
err(1, "unable to limit capability rights");
}
getfdtype(&in);
cap_rights_init(&rights, CAP_READ, CAP_SEEK);
if (cap_rights_limit(in.fd, &rights) == -1 && errno != ENOSYS)
err(1, "unable to limit capability rights");
if (files_cnt > 1 && !(in.flags & ISTAPE))
errx(1, "files is not supported for non-tape devices");
cap_rights_set(&rights, CAP_FTRUNCATE, CAP_IOCTL, CAP_WRITE);
if (out.name == NULL) {
/* No way to check for read access here. */
out.fd = STDOUT_FILENO;
@ -156,13 +172,27 @@ setup(void)
if (out.fd == -1) {
out.fd = open(out.name, O_WRONLY | OFLAGS, DEFFILEMODE);
out.flags |= NOREAD;
cap_rights_clear(&rights, CAP_READ);
}
if (out.fd == -1)
err(1, "%s", out.name);
if (caph_limit_stdout() == -1)
err(1, "unable to limit capability rights");
}
getfdtype(&out);
if (cap_rights_limit(out.fd, &rights) == -1 && errno != ENOSYS)
err(1, "unable to limit capability rights");
if (cap_ioctls_limit(out.fd, cmds, nitems(cmds)) == -1 &&
errno != ENOSYS)
err(1, "unable to limit capability rights");
if (in.fd != STDERR_FILENO && out.fd != STDERR_FILENO) {
if (caph_limit_stderr() == -1)
err(1, "unable to limit capability rights");
}
/*
* Allocate space for the input and output buffers. If not doing
* record oriented I/O, only need a single buffer.

View File

@ -120,11 +120,12 @@ command(KINFO *k, VARENT *ve)
if (cflag) {
/* If it is the last field, then don't pad */
if (STAILQ_NEXT(ve, next_ve) == NULL) {
asprintf(&str, "%s%s%s%s",
asprintf(&str, "%s%s%s%s%s",
k->ki_d.prefix ? k->ki_d.prefix : "",
k->ki_p->ki_comm,
(showthreads && k->ki_p->ki_numthreads > 1) ? "/" : "",
(showthreads && k->ki_p->ki_numthreads > 1) ? k->ki_p->ki_tdname : "");
(showthreads && k->ki_p->ki_numthreads > 1) ? k->ki_p->ki_tdname : "",
(showthreads && k->ki_p->ki_numthreads > 1) ? k->ki_p->ki_moretdname : "");
} else
str = strdup(k->ki_p->ki_comm);
@ -172,14 +173,16 @@ ucomm(KINFO *k, VARENT *ve)
char *str;
if (STAILQ_NEXT(ve, next_ve) == NULL) { /* last field, don't pad */
asprintf(&str, "%s%s%s%s",
asprintf(&str, "%s%s%s%s%s",
k->ki_d.prefix ? k->ki_d.prefix : "",
k->ki_p->ki_comm,
(showthreads && k->ki_p->ki_numthreads > 1) ? "/" : "",
(showthreads && k->ki_p->ki_numthreads > 1) ? k->ki_p->ki_tdname : "");
(showthreads && k->ki_p->ki_numthreads > 1) ? k->ki_p->ki_tdname : "",
(showthreads && k->ki_p->ki_numthreads > 1) ? k->ki_p->ki_moretdname : "");
} else {
if (showthreads && k->ki_p->ki_numthreads > 1)
asprintf(&str, "%s/%s", k->ki_p->ki_comm, k->ki_p->ki_tdname);
asprintf(&str, "%s/%s%s", k->ki_p->ki_comm,
k->ki_p->ki_tdname, k->ki_p->ki_moretdname);
else
str = strdup(k->ki_p->ki_comm);
}
@ -192,7 +195,8 @@ tdnam(KINFO *k, VARENT *ve __unused)
char *str;
if (showthreads && k->ki_p->ki_numthreads > 1)
str = strdup(k->ki_p->ki_tdname);
asprintf(&str, "%s%s", k->ki_p->ki_tdname,
k->ki_p->ki_moretdname);
else
str = strdup(" ");

View File

@ -38,9 +38,6 @@
#define PR_RLC 0x0001
#define PR_KLC 0x0002
#define PGRAB_RDONLY O_RDONLY
#define PGRAB_FORCE 0
#include_next <libproc.h>
#endif

View File

@ -56,7 +56,7 @@ prov.h: prov.d
$dtrace -h -s prov.d
prov.o: prov.d main.o
$dtrace -G -32 -s prov.d main.o
$dtrace -G -s prov.d main.o
EOF
cat > prov.d <<EOF

View File

@ -45,7 +45,7 @@ EOF
spinny()
{
while true; do
/usr/bin/date > /dev/null
/bin/date > /dev/null
done
}

View File

@ -45,7 +45,7 @@ EOF
spinny()
{
while true; do
/usr/bin/date > /dev/null
/bin/date > /dev/null
done
}

View File

@ -45,7 +45,7 @@ EOF
spinny()
{
while true; do
/usr/bin/date > /dev/null
/bin/date > /dev/null
done
}

View File

@ -729,8 +729,13 @@ dt_pid_create_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb)
(void) snprintf(provname, sizeof (provname), "pid%d", (int)pid);
if (gmatch(provname, pdp->dtpd_provider) != 0) {
#ifdef __FreeBSD__
if ((P = dt_proc_grab(dtp, pid, 0, 1)) == NULL)
#else
if ((P = dt_proc_grab(dtp, pid, PGRAB_RDONLY | PGRAB_FORCE,
0)) == NULL) {
0)) == NULL)
#endif
{
(void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_GRAB,
"failed to grab process %d", (int)pid);
return (-1);

View File

@ -34,6 +34,9 @@
* Functions sorted alphabetically.
*/
#define PR_LMID_EVERY 0
#define PGRAB_RDONLY PATTACH_RDONLY
#define PGRAB_FORCE PATTACH_FORCE
#define Psetrun(p, a1, a2) proc_continue((p))
#define Pxlookup_by_addr(p, a, n, s, sym, i) \
proc_addr2sym(p, a, n, s, sym)
@ -44,7 +47,7 @@
#define Pdelbkpt proc_bkptdel
#define Pgrab_error strerror
#define Plmid(p, a, l) (-1)
#define Plmid_to_map(p, l, o) proc_obj2map((p), (o))
#define Plmid_to_map(p, l, o) proc_name2map(p, o)
#define Plookup_by_addr proc_addr2sym
#define Pname_to_ctf(p, obj) (ctf_file_t *)proc_name2ctf(p, obj)
#define Pname_to_map proc_name2map

View File

@ -70,7 +70,7 @@ runtest()
err.*.ksh|tst.*.ksh)
expr "$TFILE" : 'err.*' >/dev/null && exstatus=1
ksh "$TFILE" /usr/sbin/dtrace >$STDOUT 2>$STDERR
tst=$TFILE ksh "$TFILE" /usr/sbin/dtrace >$STDOUT 2>$STDERR
status=$?
if [ $status -ne $exstatus ]; then

View File

@ -128,9 +128,6 @@ exclude EXFAIL common/ip/tst.ipv4remoteicmp.ksh
exclude EXFAIL common/ip/tst.localtcpstate.ksh
exclude EXFAIL common/ip/tst.remotetcpstate.ksh
# Depends on the number of probes in /bin/sh and the current DOF limit.
exclude EXFAIL common/pid/err.D_PROC_CREATEFAIL.many.d
# Tries to enable pid$target:libc::entry, though there's no "libc" module.
# Currently unsure as to whether this might be a libproc bug.
exclude EXFAIL common/pid/tst.probemod.ksh

View File

@ -2112,7 +2112,7 @@ dwarf_reg(unsigned int mach, unsigned int reg)
static void
dump_ehdr(struct readelf *re)
{
size_t shnum, shstrndx;
size_t phnum, shnum, shstrndx;
int i;
printf("ELF Header:\n");
@ -2174,7 +2174,13 @@ dump_ehdr(struct readelf *re)
re->ehdr.e_phentsize);
/* e_phnum. */
printf("%-37s%u\n", " Number of program headers:", re->ehdr.e_phnum);
printf("%-37s%u", " Number of program headers:", re->ehdr.e_phnum);
if (re->ehdr.e_phnum == PN_XNUM) {
/* Extended program header numbering is in use. */
if (elf_getphnum(re->elf, &phnum))
printf(" (%zu)", phnum);
}
putchar('\n');
/* e_shentsize. */
printf("%-37s%u (bytes)\n", " Size of section headers:",
@ -6551,14 +6557,15 @@ load_sections(struct readelf *re)
}
if ((name = elf_strptr(re->elf, shstrndx, sh.sh_name)) == NULL) {
(void) elf_errno();
name = "ERROR";
name = "<no-name>";
}
if ((ndx = elf_ndxscn(scn)) == SHN_UNDEF) {
if ((elferr = elf_errno()) != 0)
if ((elferr = elf_errno()) != 0) {
warnx("elf_ndxscn failed: %s",
elf_errmsg(elferr));
continue;
}
}
if (ndx >= re->shnum) {
warnx("section index of '%s' out of range", name);
continue;

View File

@ -4,6 +4,33 @@ brevity. Much more detail can be found in the git revision history:
https://github.com/jemalloc/jemalloc
* 4.4.0 (December 3, 2016)
New features:
- Add configure support for *-*-linux-android. (@cferris1000, @jasone)
- Add the --disable-syscall configure option, for use on systems that place
security-motivated limitations on syscall(2). (@jasone)
- Add support for Debian GNU/kFreeBSD. (@thesam)
Optimizations:
- Add extent serial numbers and use them where appropriate as a sort key that
is higher priority than address, so that the allocation policy prefers older
extents. This tends to improve locality (decrease fragmentation) when
memory grows downward. (@jasone)
- Refactor madvise(2) configuration so that MADV_FREE is detected and utilized
on Linux 4.5 and newer. (@jasone)
- Mark partially purged arena chunks as non-huge-page. This improves
interaction with Linux's transparent huge page functionality. (@jasone)
Bug fixes:
- Fix size class computations for edge conditions involving extremely large
allocations. This regression was first released in 4.0.0. (@jasone,
@ingvarha)
- Remove overly restrictive assertions related to the cactive statistic. This
regression was first released in 4.1.0. (@jasone)
- Implement a more reliable detection scheme for os_unfair_lock on macOS.
(@jszakmeister)
* 4.3.1 (November 7, 2016)
Bug fixes:

View File

@ -1,5 +1,5 @@
diff --git a/doc/jemalloc.xml.in b/doc/jemalloc.xml.in
index 3d2e721..b361db2 100644
index d9c8345..9898c3c 100644
--- a/doc/jemalloc.xml.in
+++ b/doc/jemalloc.xml.in
@@ -53,11 +53,23 @@
@ -47,10 +47,10 @@ index 3d2e721..b361db2 100644
+ </refsect1>
</refentry>
diff --git a/include/jemalloc/internal/arena.h b/include/jemalloc/internal/arena.h
index f39ce54..a3ba55d 100644
index ce4e602..35360b6 100644
--- a/include/jemalloc/internal/arena.h
+++ b/include/jemalloc/internal/arena.h
@@ -719,8 +719,13 @@ arena_miscelm_get_mutable(arena_chunk_t *chunk, size_t pageind)
@@ -730,8 +730,13 @@ arena_miscelm_get_mutable(arena_chunk_t *chunk, size_t pageind)
JEMALLOC_ALWAYS_INLINE const arena_chunk_map_misc_t *
arena_miscelm_get_const(const arena_chunk_t *chunk, size_t pageind)
{
@ -64,7 +64,7 @@ index f39ce54..a3ba55d 100644
}
JEMALLOC_ALWAYS_INLINE size_t
@@ -779,8 +784,13 @@ arena_mapbitsp_get_mutable(arena_chunk_t *chunk, size_t pageind)
@@ -790,8 +795,13 @@ arena_mapbitsp_get_mutable(arena_chunk_t *chunk, size_t pageind)
JEMALLOC_ALWAYS_INLINE const size_t *
arena_mapbitsp_get_const(const arena_chunk_t *chunk, size_t pageind)
{
@ -79,7 +79,7 @@ index f39ce54..a3ba55d 100644
JEMALLOC_ALWAYS_INLINE size_t
diff --git a/include/jemalloc/internal/jemalloc_internal.h.in b/include/jemalloc/internal/jemalloc_internal.h.in
index fdc8fef..56a35a4 100644
index e7ace7d..d86c61d 100644
--- a/include/jemalloc/internal/jemalloc_internal.h.in
+++ b/include/jemalloc/internal/jemalloc_internal.h.in
@@ -8,6 +8,9 @@
@ -144,10 +144,10 @@ index b442d2d..76518db 100644
#endif /* JEMALLOC_H_EXTERNS */
diff --git a/include/jemalloc/internal/private_symbols.txt b/include/jemalloc/internal/private_symbols.txt
index 87c8c9b..df576f6 100644
index c1c6c40..c6395fd 100644
--- a/include/jemalloc/internal/private_symbols.txt
+++ b/include/jemalloc/internal/private_symbols.txt
@@ -307,7 +307,6 @@ iralloct_realign
@@ -310,7 +310,6 @@ iralloct_realign
isalloc
isdalloct
isqalloc
@ -335,7 +335,7 @@ index f943891..47d032c 100755
+#include "jemalloc_FreeBSD.h"
EOF
diff --git a/src/jemalloc.c b/src/jemalloc.c
index 38650ff..f659b55 100644
index baead66..8a49f26 100644
--- a/src/jemalloc.c
+++ b/src/jemalloc.c
@@ -4,6 +4,10 @@
@ -349,7 +349,7 @@ index 38650ff..f659b55 100644
/* Runtime configuration options. */
const char *je_malloc_conf
#ifndef _WIN32
@@ -2756,6 +2760,107 @@ je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr)
@@ -2775,6 +2779,107 @@ je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr)
*/
/******************************************************************************/
/*
@ -457,7 +457,7 @@ index 38650ff..f659b55 100644
* The following functions are used by threading libraries for protection of
* malloc during fork().
*/
@@ -2894,4 +2999,11 @@ jemalloc_postfork_child(void)
@@ -2913,4 +3018,11 @@ jemalloc_postfork_child(void)
ctl_postfork_child(tsd_tsdn(tsd));
}
@ -516,7 +516,7 @@ index 6333e73..13f8d79 100644
+#endif
+}
diff --git a/src/util.c b/src/util.c
index 7905267..bee1c77 100644
index dd8c236..a4ff287 100755
--- a/src/util.c
+++ b/src/util.c
@@ -67,6 +67,22 @@ wrtmessage(void *cbopaque, const char *s)

View File

@ -1 +1 @@
4.3.1-0-g0110fa8451af905affd77c3bea0d545fee2251b2
4.4.0-0-gf1f76357313e7dcad7262f17a48ff0a2e005fcdc

View File

@ -2,12 +2,12 @@
.\" Title: JEMALLOC
.\" Author: Jason Evans
.\" Generator: DocBook XSL Stylesheets v1.76.1 <http://docbook.sf.net/>
.\" Date: 11/08/2016
.\" Date: 12/04/2016
.\" Manual: User Manual
.\" Source: jemalloc 4.3.1-0-g0110fa8451af905affd77c3bea0d545fee2251b2
.\" Source: jemalloc 4.4.0-0-gf1f76357313e7dcad7262f17a48ff0a2e005fcdc
.\" Language: English
.\"
.TH "JEMALLOC" "3" "11/08/2016" "jemalloc 4.3.1-0-g0110fa8451af" "User Manual"
.TH "JEMALLOC" "3" "12/04/2016" "jemalloc 4.4.0-0-gf1f76357313e" "User Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@ -31,7 +31,7 @@
jemalloc \- general purpose memory allocation functions
.SH "LIBRARY"
.PP
This manual describes jemalloc 4\&.3\&.1\-0\-g0110fa8451af905affd77c3bea0d545fee2251b2\&. More information can be found at the
This manual describes jemalloc 4\&.4\&.0\-0\-gf1f76357313e7dcad7262f17a48ff0a2e005fcdc\&. More information can be found at the
\m[blue]\fBjemalloc website\fR\m[]\&\s-2\u[1]\d\s+2\&.
.PP
The following configuration options are enabled in libc\*(Aqs built\-in jemalloc:
@ -365,7 +365,7 @@ for (i = 0; i < nbins; i++) {
mib[2] = i;
len = sizeof(bin_size);
mallctlbymib(mib, miblen, &bin_size, &len, NULL, 0);
mallctlbymib(mib, miblen, (void *)&bin_size, &len, NULL, 0);
/* Do something with bin_size\&.\&.\&. */
}
.fi

View File

@ -190,6 +190,14 @@ struct arena_chunk_s {
*/
extent_node_t node;
/*
* True if memory could be backed by transparent huge pages. This is
* only directly relevant to Linux, since it is the only supported
* platform on which jemalloc interacts with explicit transparent huge
* page controls.
*/
bool hugepage;
/*
* Map of pages within chunk that keeps track of free/large/small. The
* first map_bias entries are omitted, since the chunk header does not
@ -374,10 +382,12 @@ struct arena_s {
dss_prec_t dss_prec;
/* Extant arena chunks. */
ql_head(extent_node_t) achunks;
/* Extent serial number generator state. */
size_t extent_sn_next;
/*
* In order to avoid rapid chunk allocation/deallocation when an arena
* oscillates right on the cusp of needing a new chunk, cache the most
@ -453,9 +463,9 @@ struct arena_s {
* orderings are needed, which is why there are two trees with the same
* contents.
*/
extent_tree_t chunks_szad_cached;
extent_tree_t chunks_szsnad_cached;
extent_tree_t chunks_ad_cached;
extent_tree_t chunks_szad_retained;
extent_tree_t chunks_szsnad_retained;
extent_tree_t chunks_ad_retained;
malloc_mutex_t chunks_mtx;
@ -522,13 +532,13 @@ void arena_chunk_cache_maybe_remove(arena_t *arena, extent_node_t *node,
extent_node_t *arena_node_alloc(tsdn_t *tsdn, arena_t *arena);
void arena_node_dalloc(tsdn_t *tsdn, arena_t *arena, extent_node_t *node);
void *arena_chunk_alloc_huge(tsdn_t *tsdn, arena_t *arena, size_t usize,
size_t alignment, bool *zero);
size_t alignment, size_t *sn, bool *zero);
void arena_chunk_dalloc_huge(tsdn_t *tsdn, arena_t *arena, void *chunk,
size_t usize);
size_t usize, size_t sn);
void arena_chunk_ralloc_huge_similar(tsdn_t *tsdn, arena_t *arena,
void *chunk, size_t oldsize, size_t usize);
void arena_chunk_ralloc_huge_shrink(tsdn_t *tsdn, arena_t *arena,
void *chunk, size_t oldsize, size_t usize);
void *chunk, size_t oldsize, size_t usize, size_t sn);
bool arena_chunk_ralloc_huge_expand(tsdn_t *tsdn, arena_t *arena,
void *chunk, size_t oldsize, size_t usize, bool *zero);
ssize_t arena_lg_dirty_mult_get(tsdn_t *tsdn, arena_t *arena);
@ -601,6 +611,7 @@ void arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads,
unsigned arena_nthreads_get(arena_t *arena, bool internal);
void arena_nthreads_inc(arena_t *arena, bool internal);
void arena_nthreads_dec(arena_t *arena, bool internal);
size_t arena_extent_sn_next(arena_t *arena);
arena_t *arena_new(tsdn_t *tsdn, unsigned ind);
void arena_boot(void);
void arena_prefork0(tsdn_t *tsdn, arena_t *arena);

View File

@ -58,15 +58,16 @@ void chunk_deregister(const void *chunk, const extent_node_t *node);
void *chunk_alloc_base(size_t size);
void *chunk_alloc_cache(tsdn_t *tsdn, arena_t *arena,
chunk_hooks_t *chunk_hooks, void *new_addr, size_t size, size_t alignment,
bool *zero, bool *commit, bool dalloc_node);
size_t *sn, bool *zero, bool *commit, bool dalloc_node);
void *chunk_alloc_wrapper(tsdn_t *tsdn, arena_t *arena,
chunk_hooks_t *chunk_hooks, void *new_addr, size_t size, size_t alignment,
bool *zero, bool *commit);
size_t *sn, bool *zero, bool *commit);
void chunk_dalloc_cache(tsdn_t *tsdn, arena_t *arena,
chunk_hooks_t *chunk_hooks, void *chunk, size_t size, bool committed);
void chunk_dalloc_wrapper(tsdn_t *tsdn, arena_t *arena,
chunk_hooks_t *chunk_hooks, void *chunk, size_t size, bool zeroed,
chunk_hooks_t *chunk_hooks, void *chunk, size_t size, size_t sn,
bool committed);
void chunk_dalloc_wrapper(tsdn_t *tsdn, arena_t *arena,
chunk_hooks_t *chunk_hooks, void *chunk, size_t size, size_t sn,
bool zeroed, bool committed);
bool chunk_purge_wrapper(tsdn_t *tsdn, arena_t *arena,
chunk_hooks_t *chunk_hooks, void *chunk, size_t size, size_t offset,
size_t length);

View File

@ -18,6 +18,20 @@ struct extent_node_s {
/* Total region size. */
size_t en_size;
/*
* Serial number (potentially non-unique).
*
* In principle serial numbers can wrap around on 32-bit systems if
* JEMALLOC_MUNMAP is defined, but as long as comparison functions fall
* back on address comparison for equal serial numbers, stable (if
* imperfect) ordering is maintained.
*
* Serial numbers may not be unique even in the absence of wrap-around,
* e.g. when splitting an extent and assigning the same serial number to
* both resulting adjacent extents.
*/
size_t en_sn;
/*
* The zeroed flag is used by chunk recycling code to track whether
* memory is zero-filled.
@ -45,8 +59,8 @@ struct extent_node_s {
qr(extent_node_t) cc_link;
union {
/* Linkage for the size/address-ordered tree. */
rb_node(extent_node_t) szad_link;
/* Linkage for the size/sn/address-ordered tree. */
rb_node(extent_node_t) szsnad_link;
/* Linkage for arena's achunks, huge, and node_cache lists. */
ql_elm(extent_node_t) ql_link;
@ -61,7 +75,7 @@ typedef rb_tree(extent_node_t) extent_tree_t;
/******************************************************************************/
#ifdef JEMALLOC_H_EXTERNS
rb_proto(, extent_tree_szad_, extent_tree_t, extent_node_t)
rb_proto(, extent_tree_szsnad_, extent_tree_t, extent_node_t)
rb_proto(, extent_tree_ad_, extent_tree_t, extent_node_t)
@ -73,6 +87,7 @@ rb_proto(, extent_tree_ad_, extent_tree_t, extent_node_t)
arena_t *extent_node_arena_get(const extent_node_t *node);
void *extent_node_addr_get(const extent_node_t *node);
size_t extent_node_size_get(const extent_node_t *node);
size_t extent_node_sn_get(const extent_node_t *node);
bool extent_node_zeroed_get(const extent_node_t *node);
bool extent_node_committed_get(const extent_node_t *node);
bool extent_node_achunk_get(const extent_node_t *node);
@ -80,12 +95,13 @@ prof_tctx_t *extent_node_prof_tctx_get(const extent_node_t *node);
void extent_node_arena_set(extent_node_t *node, arena_t *arena);
void extent_node_addr_set(extent_node_t *node, void *addr);
void extent_node_size_set(extent_node_t *node, size_t size);
void extent_node_sn_set(extent_node_t *node, size_t sn);
void extent_node_zeroed_set(extent_node_t *node, bool zeroed);
void extent_node_committed_set(extent_node_t *node, bool committed);
void extent_node_achunk_set(extent_node_t *node, bool achunk);
void extent_node_prof_tctx_set(extent_node_t *node, prof_tctx_t *tctx);
void extent_node_init(extent_node_t *node, arena_t *arena, void *addr,
size_t size, bool zeroed, bool committed);
size_t size, size_t sn, bool zeroed, bool committed);
void extent_node_dirty_linkage_init(extent_node_t *node);
void extent_node_dirty_insert(extent_node_t *node,
arena_runs_dirty_link_t *runs_dirty, extent_node_t *chunks_dirty);
@ -114,6 +130,13 @@ extent_node_size_get(const extent_node_t *node)
return (node->en_size);
}
JEMALLOC_INLINE size_t
extent_node_sn_get(const extent_node_t *node)
{
return (node->en_sn);
}
JEMALLOC_INLINE bool
extent_node_zeroed_get(const extent_node_t *node)
{
@ -164,6 +187,13 @@ extent_node_size_set(extent_node_t *node, size_t size)
node->en_size = size;
}
JEMALLOC_INLINE void
extent_node_sn_set(extent_node_t *node, size_t sn)
{
node->en_sn = sn;
}
JEMALLOC_INLINE void
extent_node_zeroed_set(extent_node_t *node, bool zeroed)
{
@ -194,12 +224,13 @@ extent_node_prof_tctx_set(extent_node_t *node, prof_tctx_t *tctx)
JEMALLOC_INLINE void
extent_node_init(extent_node_t *node, arena_t *arena, void *addr, size_t size,
bool zeroed, bool committed)
size_t sn, bool zeroed, bool committed)
{
extent_node_arena_set(node, arena);
extent_node_addr_set(node, addr);
extent_node_size_set(node, size);
extent_node_sn_set(node, sn);
extent_node_zeroed_set(node, zeroed);
extent_node_committed_set(node, committed);
extent_node_achunk_set(node, false);

View File

@ -334,7 +334,7 @@ typedef unsigned szind_t;
/* Return the nearest aligned address at or below a. */
#define ALIGNMENT_ADDR2BASE(a, alignment) \
((void *)((uintptr_t)(a) & (-(alignment))))
((void *)((uintptr_t)(a) & ((~(alignment)) + 1)))
/* Return the offset between a and the nearest aligned address at or below a. */
#define ALIGNMENT_ADDR2OFFSET(a, alignment) \
@ -342,7 +342,7 @@ typedef unsigned szind_t;
/* Return the smallest alignment multiple that is >= s. */
#define ALIGNMENT_CEILING(s, alignment) \
(((s) + (alignment - 1)) & (-(alignment)))
(((s) + (alignment - 1)) & ((~(alignment)) + 1))
/* Declare a variable-length array. */
#if __STDC_VERSION__ < 199901L

View File

@ -56,11 +56,6 @@
*/
#define JEMALLOC_HAVE_BUILTIN_CLZ
/*
* Defined if madvise(2) is available.
*/
#define JEMALLOC_HAVE_MADVISE
/*
* Defined if os_unfair_lock_*() functions are available, as provided by Darwin.
*/
@ -72,8 +67,8 @@
*/
/* #undef JEMALLOC_OSSPIN */
/* Defined if syscall(2) is available. */
#define JEMALLOC_HAVE_SYSCALL
/* Defined if syscall(2) is usable. */
#define JEMALLOC_USE_SYSCALL
/*
* Defined if secure_getenv(3) is available.
@ -85,6 +80,9 @@
*/
#define JEMALLOC_HAVE_ISSETUGID
/* Defined if pthread_atfork(3) is available. */
#define JEMALLOC_HAVE_PTHREAD_ATFORK
/*
* Defined if clock_gettime(CLOCK_MONOTONIC_COARSE, ...) is available.
*/
@ -253,18 +251,26 @@
#define JEMALLOC_SYSCTL_VM_OVERCOMMIT
/* #undef JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY */
/* Defined if madvise(2) is available. */
#define JEMALLOC_HAVE_MADVISE
/*
* Methods for purging unused pages differ between operating systems.
*
* madvise(..., MADV_DONTNEED) : On Linux, this immediately discards pages,
* such that new pages will be demand-zeroed if
* the address region is later touched.
* madvise(..., MADV_FREE) : On FreeBSD and Darwin, this marks pages as being
* unused, such that they will be discarded rather
* than swapped out.
* madvise(..., MADV_FREE) : This marks pages as being unused, such that they
* will be discarded rather than swapped out.
* madvise(..., MADV_DONTNEED) : This immediately discards pages, such that
* new pages will be demand-zeroed if the
* address region is later touched.
*/
/* #undef JEMALLOC_PURGE_MADVISE_DONTNEED */
#define JEMALLOC_PURGE_MADVISE_FREE
#define JEMALLOC_PURGE_MADVISE_DONTNEED
/*
* Defined if transparent huge pages are supported via the MADV_[NO]HUGEPAGE
* arguments to madvise(2).
*/
/* #undef JEMALLOC_THP */
/* Define if operating system has alloca.h header. */
/* #undef JEMALLOC_HAS_ALLOCA_H */

View File

@ -16,6 +16,8 @@ void *pages_trim(void *addr, size_t alloc_size, size_t leadsize,
bool pages_commit(void *addr, size_t size);
bool pages_decommit(void *addr, size_t size);
bool pages_purge(void *addr, size_t size);
bool pages_huge(void *addr, size_t size);
bool pages_nohuge(void *addr, size_t size);
void pages_boot(void);
#endif /* JEMALLOC_H_EXTERNS */

View File

@ -36,6 +36,7 @@
#define arena_decay_time_set JEMALLOC_N(arena_decay_time_set)
#define arena_dss_prec_get JEMALLOC_N(arena_dss_prec_get)
#define arena_dss_prec_set JEMALLOC_N(arena_dss_prec_set)
#define arena_extent_sn_next JEMALLOC_N(arena_extent_sn_next)
#define arena_get JEMALLOC_N(arena_get)
#define arena_ichoose JEMALLOC_N(arena_ichoose)
#define arena_init JEMALLOC_N(arena_init)
@ -218,6 +219,8 @@
#define extent_node_prof_tctx_set JEMALLOC_N(extent_node_prof_tctx_set)
#define extent_node_size_get JEMALLOC_N(extent_node_size_get)
#define extent_node_size_set JEMALLOC_N(extent_node_size_set)
#define extent_node_sn_get JEMALLOC_N(extent_node_sn_get)
#define extent_node_sn_set JEMALLOC_N(extent_node_sn_set)
#define extent_node_zeroed_get JEMALLOC_N(extent_node_zeroed_get)
#define extent_node_zeroed_set JEMALLOC_N(extent_node_zeroed_set)
#define extent_tree_ad_destroy JEMALLOC_N(extent_tree_ad_destroy)
@ -239,25 +242,25 @@
#define extent_tree_ad_reverse_iter_recurse JEMALLOC_N(extent_tree_ad_reverse_iter_recurse)
#define extent_tree_ad_reverse_iter_start JEMALLOC_N(extent_tree_ad_reverse_iter_start)
#define extent_tree_ad_search JEMALLOC_N(extent_tree_ad_search)
#define extent_tree_szad_destroy JEMALLOC_N(extent_tree_szad_destroy)
#define extent_tree_szad_destroy_recurse JEMALLOC_N(extent_tree_szad_destroy_recurse)
#define extent_tree_szad_empty JEMALLOC_N(extent_tree_szad_empty)
#define extent_tree_szad_first JEMALLOC_N(extent_tree_szad_first)
#define extent_tree_szad_insert JEMALLOC_N(extent_tree_szad_insert)
#define extent_tree_szad_iter JEMALLOC_N(extent_tree_szad_iter)
#define extent_tree_szad_iter_recurse JEMALLOC_N(extent_tree_szad_iter_recurse)
#define extent_tree_szad_iter_start JEMALLOC_N(extent_tree_szad_iter_start)
#define extent_tree_szad_last JEMALLOC_N(extent_tree_szad_last)
#define extent_tree_szad_new JEMALLOC_N(extent_tree_szad_new)
#define extent_tree_szad_next JEMALLOC_N(extent_tree_szad_next)
#define extent_tree_szad_nsearch JEMALLOC_N(extent_tree_szad_nsearch)
#define extent_tree_szad_prev JEMALLOC_N(extent_tree_szad_prev)
#define extent_tree_szad_psearch JEMALLOC_N(extent_tree_szad_psearch)
#define extent_tree_szad_remove JEMALLOC_N(extent_tree_szad_remove)
#define extent_tree_szad_reverse_iter JEMALLOC_N(extent_tree_szad_reverse_iter)
#define extent_tree_szad_reverse_iter_recurse JEMALLOC_N(extent_tree_szad_reverse_iter_recurse)
#define extent_tree_szad_reverse_iter_start JEMALLOC_N(extent_tree_szad_reverse_iter_start)
#define extent_tree_szad_search JEMALLOC_N(extent_tree_szad_search)
#define extent_tree_szsnad_destroy JEMALLOC_N(extent_tree_szsnad_destroy)
#define extent_tree_szsnad_destroy_recurse JEMALLOC_N(extent_tree_szsnad_destroy_recurse)
#define extent_tree_szsnad_empty JEMALLOC_N(extent_tree_szsnad_empty)
#define extent_tree_szsnad_first JEMALLOC_N(extent_tree_szsnad_first)
#define extent_tree_szsnad_insert JEMALLOC_N(extent_tree_szsnad_insert)
#define extent_tree_szsnad_iter JEMALLOC_N(extent_tree_szsnad_iter)
#define extent_tree_szsnad_iter_recurse JEMALLOC_N(extent_tree_szsnad_iter_recurse)
#define extent_tree_szsnad_iter_start JEMALLOC_N(extent_tree_szsnad_iter_start)
#define extent_tree_szsnad_last JEMALLOC_N(extent_tree_szsnad_last)
#define extent_tree_szsnad_new JEMALLOC_N(extent_tree_szsnad_new)
#define extent_tree_szsnad_next JEMALLOC_N(extent_tree_szsnad_next)
#define extent_tree_szsnad_nsearch JEMALLOC_N(extent_tree_szsnad_nsearch)
#define extent_tree_szsnad_prev JEMALLOC_N(extent_tree_szsnad_prev)
#define extent_tree_szsnad_psearch JEMALLOC_N(extent_tree_szsnad_psearch)
#define extent_tree_szsnad_remove JEMALLOC_N(extent_tree_szsnad_remove)
#define extent_tree_szsnad_reverse_iter JEMALLOC_N(extent_tree_szsnad_reverse_iter)
#define extent_tree_szsnad_reverse_iter_recurse JEMALLOC_N(extent_tree_szsnad_reverse_iter_recurse)
#define extent_tree_szsnad_reverse_iter_start JEMALLOC_N(extent_tree_szsnad_reverse_iter_start)
#define extent_tree_szsnad_search JEMALLOC_N(extent_tree_szsnad_search)
#define ffs_llu JEMALLOC_N(ffs_llu)
#define ffs_lu JEMALLOC_N(ffs_lu)
#define ffs_u JEMALLOC_N(ffs_u)
@ -393,7 +396,9 @@
#define pages_boot JEMALLOC_N(pages_boot)
#define pages_commit JEMALLOC_N(pages_commit)
#define pages_decommit JEMALLOC_N(pages_decommit)
#define pages_huge JEMALLOC_N(pages_huge)
#define pages_map JEMALLOC_N(pages_map)
#define pages_nohuge JEMALLOC_N(pages_nohuge)
#define pages_purge JEMALLOC_N(pages_purge)
#define pages_trim JEMALLOC_N(pages_trim)
#define pages_unmap JEMALLOC_N(pages_unmap)

View File

@ -175,25 +175,21 @@ stats_cactive_get(void)
JEMALLOC_INLINE void
stats_cactive_add(size_t size)
{
UNUSED size_t cactive;
assert(size > 0);
assert((size & chunksize_mask) == 0);
cactive = atomic_add_z(&stats_cactive, size);
assert(cactive - size < cactive);
atomic_add_z(&stats_cactive, size);
}
JEMALLOC_INLINE void
stats_cactive_sub(size_t size)
{
UNUSED size_t cactive;
assert(size > 0);
assert((size & chunksize_mask) == 0);
cactive = atomic_sub_z(&stats_cactive, size);
assert(cactive + size > cactive);
atomic_sub_z(&stats_cactive, size);
}
#endif

View File

@ -41,8 +41,12 @@
#define MALLOC_PRINTF_BUFSIZE 4096
/* Junk fill patterns. */
#ifndef JEMALLOC_ALLOC_JUNK
# define JEMALLOC_ALLOC_JUNK ((uint8_t)0xa5)
#endif
#ifndef JEMALLOC_FREE_JUNK
# define JEMALLOC_FREE_JUNK ((uint8_t)0x5a)
#endif
/*
* Wrap a cpp argument that contains commas such that it isn't broken up into

View File

@ -36,13 +36,25 @@
zero); \
} \
} while (0)
#define JEMALLOC_VALGRIND_REALLOC(maybe_moved, tsdn, ptr, usize, \
ptr_maybe_null, old_ptr, old_usize, old_rzsize, old_ptr_maybe_null, \
zero) do { \
#define JEMALLOC_VALGRIND_REALLOC_MOVED_no(ptr, old_ptr) \
(false)
#define JEMALLOC_VALGRIND_REALLOC_MOVED_maybe(ptr, old_ptr) \
((ptr) != (old_ptr))
#define JEMALLOC_VALGRIND_REALLOC_PTR_NULL_no(ptr) \
(false)
#define JEMALLOC_VALGRIND_REALLOC_PTR_NULL_maybe(ptr) \
(ptr == NULL)
#define JEMALLOC_VALGRIND_REALLOC_OLD_PTR_NULL_no(old_ptr) \
(false)
#define JEMALLOC_VALGRIND_REALLOC_OLD_PTR_NULL_maybe(old_ptr) \
(old_ptr == NULL)
#define JEMALLOC_VALGRIND_REALLOC(moved, tsdn, ptr, usize, ptr_null, \
old_ptr, old_usize, old_rzsize, old_ptr_null, zero) do { \
if (unlikely(in_valgrind)) { \
size_t rzsize = p2rz(tsdn, ptr); \
\
if (!maybe_moved || ptr == old_ptr) { \
if (!JEMALLOC_VALGRIND_REALLOC_MOVED_##moved(ptr, \
old_ptr)) { \
VALGRIND_RESIZEINPLACE_BLOCK(ptr, old_usize, \
usize, rzsize); \
if (zero && old_usize < usize) { \
@ -51,11 +63,13 @@
old_usize), usize - old_usize); \
} \
} else { \
if (!old_ptr_maybe_null || old_ptr != NULL) { \
if (!JEMALLOC_VALGRIND_REALLOC_OLD_PTR_NULL_## \
old_ptr_null(old_ptr)) { \
valgrind_freelike_block(old_ptr, \
old_rzsize); \
} \
if (!ptr_maybe_null || ptr != NULL) { \
if (!JEMALLOC_VALGRIND_REALLOC_PTR_NULL_## \
ptr_null(ptr)) { \
size_t copy_size = (old_usize < usize) \
? old_usize : usize; \
size_t tail_size = usize - copy_size; \

View File

@ -87,12 +87,12 @@ extern "C" {
#include <limits.h>
#include <strings.h>
#define JEMALLOC_VERSION "4.3.1-0-g0110fa8451af905affd77c3bea0d545fee2251b2"
#define JEMALLOC_VERSION "4.4.0-0-gf1f76357313e7dcad7262f17a48ff0a2e005fcdc"
#define JEMALLOC_VERSION_MAJOR 4
#define JEMALLOC_VERSION_MINOR 3
#define JEMALLOC_VERSION_BUGFIX 1
#define JEMALLOC_VERSION_MINOR 4
#define JEMALLOC_VERSION_BUGFIX 0
#define JEMALLOC_VERSION_NREV 0
#define JEMALLOC_VERSION_GID "0110fa8451af905affd77c3bea0d545fee2251b2"
#define JEMALLOC_VERSION_GID "f1f76357313e7dcad7262f17a48ff0a2e005fcdc"
# define MALLOCX_LG_ALIGN(la) ((int)(la))
# if LG_SIZEOF_PTR == 2

View File

@ -38,8 +38,8 @@ static void arena_run_dalloc(tsdn_t *tsdn, arena_t *arena, arena_run_t *run,
bool dirty, bool cleaned, bool decommitted);
static void arena_dalloc_bin_run(tsdn_t *tsdn, arena_t *arena,
arena_chunk_t *chunk, arena_run_t *run, arena_bin_t *bin);
static void arena_bin_lower_run(arena_t *arena, arena_chunk_t *chunk,
arena_run_t *run, arena_bin_t *bin);
static void arena_bin_lower_run(arena_t *arena, arena_run_t *run,
arena_bin_t *bin);
/******************************************************************************/
@ -55,8 +55,31 @@ arena_miscelm_size_get(const arena_chunk_map_misc_t *miscelm)
return (arena_mapbits_size_decode(mapbits));
}
JEMALLOC_INLINE_C const extent_node_t *
arena_miscelm_extent_get(const arena_chunk_map_misc_t *miscelm)
{
arena_chunk_t *chunk;
chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(miscelm);
return (&chunk->node);
}
JEMALLOC_INLINE_C int
arena_run_addr_comp(const arena_chunk_map_misc_t *a,
arena_sn_comp(const arena_chunk_map_misc_t *a, const arena_chunk_map_misc_t *b)
{
size_t a_sn, b_sn;
assert(a != NULL);
assert(b != NULL);
a_sn = extent_node_sn_get(arena_miscelm_extent_get(a));
b_sn = extent_node_sn_get(arena_miscelm_extent_get(b));
return ((a_sn > b_sn) - (a_sn < b_sn));
}
JEMALLOC_INLINE_C int
arena_ad_comp(const arena_chunk_map_misc_t *a,
const arena_chunk_map_misc_t *b)
{
uintptr_t a_miscelm = (uintptr_t)a;
@ -68,9 +91,26 @@ arena_run_addr_comp(const arena_chunk_map_misc_t *a,
return ((a_miscelm > b_miscelm) - (a_miscelm < b_miscelm));
}
JEMALLOC_INLINE_C int
arena_snad_comp(const arena_chunk_map_misc_t *a,
const arena_chunk_map_misc_t *b)
{
int ret;
assert(a != NULL);
assert(b != NULL);
ret = arena_sn_comp(a, b);
if (ret != 0)
return (ret);
ret = arena_ad_comp(a, b);
return (ret);
}
/* Generate pairing heap functions. */
ph_gen(static UNUSED, arena_run_heap_, arena_run_heap_t, arena_chunk_map_misc_t,
ph_link, arena_run_addr_comp)
ph_link, arena_snad_comp)
#ifdef JEMALLOC_JET
#undef run_quantize_floor
@ -529,7 +569,7 @@ arena_chunk_init_spare(arena_t *arena)
static bool
arena_chunk_register(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *chunk,
bool zero)
size_t sn, bool zero)
{
/*
@ -538,7 +578,7 @@ arena_chunk_register(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *chunk,
* of runs is tracked individually, and upon chunk deallocation the
* entire chunk is in a consistent commit state.
*/
extent_node_init(&chunk->node, arena, chunk, chunksize, zero, true);
extent_node_init(&chunk->node, arena, chunk, chunksize, sn, zero, true);
extent_node_achunk_set(&chunk->node, true);
return (chunk_register(tsdn, chunk, &chunk->node));
}
@ -548,28 +588,30 @@ arena_chunk_alloc_internal_hard(tsdn_t *tsdn, arena_t *arena,
chunk_hooks_t *chunk_hooks, bool *zero, bool *commit)
{
arena_chunk_t *chunk;
size_t sn;
malloc_mutex_unlock(tsdn, &arena->lock);
chunk = (arena_chunk_t *)chunk_alloc_wrapper(tsdn, arena, chunk_hooks,
NULL, chunksize, chunksize, zero, commit);
NULL, chunksize, chunksize, &sn, zero, commit);
if (chunk != NULL && !*commit) {
/* Commit header. */
if (chunk_hooks->commit(chunk, chunksize, 0, map_bias <<
LG_PAGE, arena->ind)) {
chunk_dalloc_wrapper(tsdn, arena, chunk_hooks,
(void *)chunk, chunksize, *zero, *commit);
(void *)chunk, chunksize, sn, *zero, *commit);
chunk = NULL;
}
}
if (chunk != NULL && arena_chunk_register(tsdn, arena, chunk, *zero)) {
if (chunk != NULL && arena_chunk_register(tsdn, arena, chunk, sn,
*zero)) {
if (!*commit) {
/* Undo commit of header. */
chunk_hooks->decommit(chunk, chunksize, 0, map_bias <<
LG_PAGE, arena->ind);
}
chunk_dalloc_wrapper(tsdn, arena, chunk_hooks, (void *)chunk,
chunksize, *zero, *commit);
chunksize, sn, *zero, *commit);
chunk = NULL;
}
@ -583,13 +625,14 @@ arena_chunk_alloc_internal(tsdn_t *tsdn, arena_t *arena, bool *zero,
{
arena_chunk_t *chunk;
chunk_hooks_t chunk_hooks = CHUNK_HOOKS_INITIALIZER;
size_t sn;
chunk = chunk_alloc_cache(tsdn, arena, &chunk_hooks, NULL, chunksize,
chunksize, zero, commit, true);
chunksize, &sn, zero, commit, true);
if (chunk != NULL) {
if (arena_chunk_register(tsdn, arena, chunk, *zero)) {
if (arena_chunk_register(tsdn, arena, chunk, sn, *zero)) {
chunk_dalloc_cache(tsdn, arena, &chunk_hooks, chunk,
chunksize, true);
chunksize, sn, true);
return (NULL);
}
}
@ -621,6 +664,8 @@ arena_chunk_init_hard(tsdn_t *tsdn, arena_t *arena)
if (chunk == NULL)
return (NULL);
chunk->hugepage = true;
/*
* Initialize the map to contain one maximal free untouched run. Mark
* the pages as zeroed if arena_chunk_alloc_internal() returned a zeroed
@ -684,11 +729,14 @@ arena_chunk_alloc(tsdn_t *tsdn, arena_t *arena)
static void
arena_chunk_discard(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *chunk)
{
size_t sn, hugepage;
bool committed;
chunk_hooks_t chunk_hooks = CHUNK_HOOKS_INITIALIZER;
chunk_deregister(chunk, &chunk->node);
sn = extent_node_sn_get(&chunk->node);
hugepage = chunk->hugepage;
committed = (arena_mapbits_decommitted_get(chunk, map_bias) == 0);
if (!committed) {
/*
@ -701,9 +749,17 @@ arena_chunk_discard(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *chunk)
chunk_hooks.decommit(chunk, chunksize, 0, map_bias << LG_PAGE,
arena->ind);
}
if (!hugepage) {
/*
* Convert chunk back to the default state, so that all
* subsequent chunk allocations start out with chunks that can
* be backed by transparent huge pages.
*/
pages_huge(chunk, chunksize);
}
chunk_dalloc_cache(tsdn, arena, &chunk_hooks, (void *)chunk, chunksize,
committed);
sn, committed);
if (config_stats) {
arena->stats.mapped -= chunksize;
@ -859,14 +915,14 @@ arena_node_dalloc(tsdn_t *tsdn, arena_t *arena, extent_node_t *node)
static void *
arena_chunk_alloc_huge_hard(tsdn_t *tsdn, arena_t *arena,
chunk_hooks_t *chunk_hooks, size_t usize, size_t alignment, bool *zero,
size_t csize)
chunk_hooks_t *chunk_hooks, size_t usize, size_t alignment, size_t *sn,
bool *zero, size_t csize)
{
void *ret;
bool commit = true;
ret = chunk_alloc_wrapper(tsdn, arena, chunk_hooks, NULL, csize,
alignment, zero, &commit);
alignment, sn, zero, &commit);
if (ret == NULL) {
/* Revert optimistic stats updates. */
malloc_mutex_lock(tsdn, &arena->lock);
@ -883,7 +939,7 @@ arena_chunk_alloc_huge_hard(tsdn_t *tsdn, arena_t *arena,
void *
arena_chunk_alloc_huge(tsdn_t *tsdn, arena_t *arena, size_t usize,
size_t alignment, bool *zero)
size_t alignment, size_t *sn, bool *zero)
{
void *ret;
chunk_hooks_t chunk_hooks = CHUNK_HOOKS_INITIALIZER;
@ -900,18 +956,19 @@ arena_chunk_alloc_huge(tsdn_t *tsdn, arena_t *arena, size_t usize,
arena_nactive_add(arena, usize >> LG_PAGE);
ret = chunk_alloc_cache(tsdn, arena, &chunk_hooks, NULL, csize,
alignment, zero, &commit, true);
alignment, sn, zero, &commit, true);
malloc_mutex_unlock(tsdn, &arena->lock);
if (ret == NULL) {
ret = arena_chunk_alloc_huge_hard(tsdn, arena, &chunk_hooks,
usize, alignment, zero, csize);
usize, alignment, sn, zero, csize);
}
return (ret);
}
void
arena_chunk_dalloc_huge(tsdn_t *tsdn, arena_t *arena, void *chunk, size_t usize)
arena_chunk_dalloc_huge(tsdn_t *tsdn, arena_t *arena, void *chunk, size_t usize,
size_t sn)
{
chunk_hooks_t chunk_hooks = CHUNK_HOOKS_INITIALIZER;
size_t csize;
@ -924,7 +981,7 @@ arena_chunk_dalloc_huge(tsdn_t *tsdn, arena_t *arena, void *chunk, size_t usize)
}
arena_nactive_sub(arena, usize >> LG_PAGE);
chunk_dalloc_cache(tsdn, arena, &chunk_hooks, chunk, csize, true);
chunk_dalloc_cache(tsdn, arena, &chunk_hooks, chunk, csize, sn, true);
malloc_mutex_unlock(tsdn, &arena->lock);
}
@ -948,7 +1005,7 @@ arena_chunk_ralloc_huge_similar(tsdn_t *tsdn, arena_t *arena, void *chunk,
void
arena_chunk_ralloc_huge_shrink(tsdn_t *tsdn, arena_t *arena, void *chunk,
size_t oldsize, size_t usize)
size_t oldsize, size_t usize, size_t sn)
{
size_t udiff = oldsize - usize;
size_t cdiff = CHUNK_CEILING(oldsize) - CHUNK_CEILING(usize);
@ -967,7 +1024,7 @@ arena_chunk_ralloc_huge_shrink(tsdn_t *tsdn, arena_t *arena, void *chunk,
CHUNK_CEILING(usize));
chunk_dalloc_cache(tsdn, arena, &chunk_hooks, nchunk, cdiff,
true);
sn, true);
}
malloc_mutex_unlock(tsdn, &arena->lock);
}
@ -975,13 +1032,13 @@ arena_chunk_ralloc_huge_shrink(tsdn_t *tsdn, arena_t *arena, void *chunk,
static bool
arena_chunk_ralloc_huge_expand_hard(tsdn_t *tsdn, arena_t *arena,
chunk_hooks_t *chunk_hooks, void *chunk, size_t oldsize, size_t usize,
bool *zero, void *nchunk, size_t udiff, size_t cdiff)
size_t *sn, bool *zero, void *nchunk, size_t udiff, size_t cdiff)
{
bool err;
bool commit = true;
err = (chunk_alloc_wrapper(tsdn, arena, chunk_hooks, nchunk, cdiff,
chunksize, zero, &commit) == NULL);
chunksize, sn, zero, &commit) == NULL);
if (err) {
/* Revert optimistic stats updates. */
malloc_mutex_lock(tsdn, &arena->lock);
@ -995,7 +1052,7 @@ arena_chunk_ralloc_huge_expand_hard(tsdn_t *tsdn, arena_t *arena,
} else if (chunk_hooks->merge(chunk, CHUNK_CEILING(oldsize), nchunk,
cdiff, true, arena->ind)) {
chunk_dalloc_wrapper(tsdn, arena, chunk_hooks, nchunk, cdiff,
*zero, true);
*sn, *zero, true);
err = true;
}
return (err);
@ -1010,6 +1067,7 @@ arena_chunk_ralloc_huge_expand(tsdn_t *tsdn, arena_t *arena, void *chunk,
void *nchunk = (void *)((uintptr_t)chunk + CHUNK_CEILING(oldsize));
size_t udiff = usize - oldsize;
size_t cdiff = CHUNK_CEILING(usize) - CHUNK_CEILING(oldsize);
size_t sn;
bool commit = true;
malloc_mutex_lock(tsdn, &arena->lock);
@ -1022,16 +1080,16 @@ arena_chunk_ralloc_huge_expand(tsdn_t *tsdn, arena_t *arena, void *chunk,
arena_nactive_add(arena, udiff >> LG_PAGE);
err = (chunk_alloc_cache(tsdn, arena, &chunk_hooks, nchunk, cdiff,
chunksize, zero, &commit, true) == NULL);
chunksize, &sn, zero, &commit, true) == NULL);
malloc_mutex_unlock(tsdn, &arena->lock);
if (err) {
err = arena_chunk_ralloc_huge_expand_hard(tsdn, arena,
&chunk_hooks, chunk, oldsize, usize, zero, nchunk, udiff,
cdiff);
&chunk_hooks, chunk, oldsize, usize, &sn, zero, nchunk,
udiff, cdiff);
} else if (chunk_hooks.merge(chunk, CHUNK_CEILING(oldsize), nchunk,
cdiff, true, arena->ind)) {
chunk_dalloc_wrapper(tsdn, arena, &chunk_hooks, nchunk, cdiff,
*zero, true);
sn, *zero, true);
err = true;
}
@ -1519,6 +1577,7 @@ arena_stash_dirty(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
if (rdelm == &chunkselm->rd) {
extent_node_t *chunkselm_next;
size_t sn;
bool zero, commit;
UNUSED void *chunk;
@ -1536,8 +1595,8 @@ arena_stash_dirty(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
commit = false;
chunk = chunk_alloc_cache(tsdn, arena, chunk_hooks,
extent_node_addr_get(chunkselm),
extent_node_size_get(chunkselm), chunksize, &zero,
&commit, false);
extent_node_size_get(chunkselm), chunksize, &sn,
&zero, &commit, false);
assert(chunk == extent_node_addr_get(chunkselm));
assert(zero == extent_node_zeroed_get(chunkselm));
extent_node_dirty_insert(chunkselm, purge_runs_sentinel,
@ -1634,6 +1693,17 @@ arena_purge_stashed(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
run_size = arena_mapbits_large_size_get(chunk, pageind);
npages = run_size >> LG_PAGE;
/*
* If this is the first run purged within chunk, mark
* the chunk as non-huge. This will prevent all use of
* transparent huge pages for this chunk until the chunk
* as a whole is deallocated.
*/
if (chunk->hugepage) {
pages_nohuge(chunk, chunksize);
chunk->hugepage = false;
}
assert(pageind + npages <= chunk_npages);
assert(!arena_mapbits_decommitted_get(chunk, pageind));
assert(!arena_mapbits_decommitted_get(chunk,
@ -1703,13 +1773,14 @@ arena_unstash_purged(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
cc_link);
void *addr = extent_node_addr_get(chunkselm);
size_t size = extent_node_size_get(chunkselm);
size_t sn = extent_node_sn_get(chunkselm);
bool zeroed = extent_node_zeroed_get(chunkselm);
bool committed = extent_node_committed_get(chunkselm);
extent_node_dirty_remove(chunkselm);
arena_node_dalloc(tsdn, arena, chunkselm);
chunkselm = chunkselm_next;
chunk_dalloc_wrapper(tsdn, arena, chunk_hooks, addr,
size, zeroed, committed);
size, sn, zeroed, committed);
} else {
arena_chunk_t *chunk =
(arena_chunk_t *)CHUNK_ADDR2BASE(rdelm);
@ -2315,7 +2386,7 @@ arena_bin_malloc_hard(tsdn_t *tsdn, arena_t *arena, arena_bin_t *bin)
arena_dalloc_bin_run(tsdn, arena, chunk, run,
bin);
} else
arena_bin_lower_run(arena, chunk, run, bin);
arena_bin_lower_run(arena, run, bin);
}
return (ret);
}
@ -2820,16 +2891,18 @@ arena_dalloc_bin_run(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *chunk,
}
static void
arena_bin_lower_run(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
arena_bin_t *bin)
arena_bin_lower_run(arena_t *arena, arena_run_t *run, arena_bin_t *bin)
{
/*
* Make sure that if bin->runcur is non-NULL, it refers to the lowest
* non-full run. It is okay to NULL runcur out rather than proactively
* keeping it pointing at the lowest non-full run.
* Make sure that if bin->runcur is non-NULL, it refers to the
* oldest/lowest non-full run. It is okay to NULL runcur out rather
* than proactively keeping it pointing at the oldest/lowest non-full
* run.
*/
if ((uintptr_t)run < (uintptr_t)bin->runcur) {
if (bin->runcur != NULL &&
arena_snad_comp(arena_run_to_miscelm(bin->runcur),
arena_run_to_miscelm(run)) > 0) {
/* Switch runcur. */
if (bin->runcur->nfree > 0)
arena_bin_runs_insert(bin, bin->runcur);
@ -2865,7 +2938,7 @@ arena_dalloc_bin_locked_impl(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *chunk,
arena_dissociate_bin_run(chunk, run, bin);
arena_dalloc_bin_run(tsdn, arena, chunk, run, bin);
} else if (run->nfree == 1 && run != bin->runcur)
arena_bin_lower_run(arena, chunk, run, bin);
arena_bin_lower_run(arena, run, bin);
if (config_stats) {
bin->stats.ndalloc++;
@ -3452,6 +3525,13 @@ arena_nthreads_dec(arena_t *arena, bool internal)
atomic_sub_u(&arena->nthreads[internal], 1);
}
size_t
arena_extent_sn_next(arena_t *arena)
{
return (atomic_add_z(&arena->extent_sn_next, 1) - 1);
}
arena_t *
arena_new(tsdn_t *tsdn, unsigned ind)
{
@ -3511,6 +3591,8 @@ arena_new(tsdn_t *tsdn, unsigned ind)
ql_new(&arena->achunks);
arena->extent_sn_next = 0;
arena->spare = NULL;
arena->lg_dirty_mult = arena_lg_dirty_mult_default_get();
@ -3532,9 +3614,9 @@ arena_new(tsdn_t *tsdn, unsigned ind)
WITNESS_RANK_ARENA_HUGE))
return (NULL);
extent_tree_szad_new(&arena->chunks_szad_cached);
extent_tree_szsnad_new(&arena->chunks_szsnad_cached);
extent_tree_ad_new(&arena->chunks_ad_cached);
extent_tree_szad_new(&arena->chunks_szad_retained);
extent_tree_szsnad_new(&arena->chunks_szsnad_retained);
extent_tree_ad_new(&arena->chunks_ad_retained);
if (malloc_mutex_init(&arena->chunks_mtx, "arena_chunks",
WITNESS_RANK_ARENA_CHUNKS))

View File

@ -5,7 +5,8 @@
/* Data. */
static malloc_mutex_t base_mtx;
static extent_tree_t base_avail_szad;
static size_t base_extent_sn_next;
static extent_tree_t base_avail_szsnad;
static extent_node_t *base_nodes;
static size_t base_allocated;
static size_t base_resident;
@ -39,6 +40,14 @@ base_node_dalloc(tsdn_t *tsdn, extent_node_t *node)
base_nodes = node;
}
static void
base_extent_node_init(extent_node_t *node, void *addr, size_t size)
{
size_t sn = atomic_add_z(&base_extent_sn_next, 1) - 1;
extent_node_init(node, NULL, addr, size, sn, true, true);
}
static extent_node_t *
base_chunk_alloc(tsdn_t *tsdn, size_t minsize)
{
@ -68,7 +77,7 @@ base_chunk_alloc(tsdn_t *tsdn, size_t minsize)
base_resident += PAGE_CEILING(nsize);
}
}
extent_node_init(node, NULL, addr, csize, true, true);
base_extent_node_init(node, addr, csize);
return (node);
}
@ -92,12 +101,12 @@ base_alloc(tsdn_t *tsdn, size_t size)
csize = CACHELINE_CEILING(size);
usize = s2u(csize);
extent_node_init(&key, NULL, NULL, usize, false, false);
extent_node_init(&key, NULL, NULL, usize, 0, false, false);
malloc_mutex_lock(tsdn, &base_mtx);
node = extent_tree_szad_nsearch(&base_avail_szad, &key);
node = extent_tree_szsnad_nsearch(&base_avail_szsnad, &key);
if (node != NULL) {
/* Use existing space. */
extent_tree_szad_remove(&base_avail_szad, node);
extent_tree_szsnad_remove(&base_avail_szsnad, node);
} else {
/* Try to allocate more space. */
node = base_chunk_alloc(tsdn, csize);
@ -111,7 +120,7 @@ base_alloc(tsdn_t *tsdn, size_t size)
if (extent_node_size_get(node) > csize) {
extent_node_addr_set(node, (void *)((uintptr_t)ret + csize));
extent_node_size_set(node, extent_node_size_get(node) - csize);
extent_tree_szad_insert(&base_avail_szad, node);
extent_tree_szsnad_insert(&base_avail_szsnad, node);
} else
base_node_dalloc(tsdn, node);
if (config_stats) {
@ -149,7 +158,8 @@ base_boot(void)
if (malloc_mutex_init(&base_mtx, "base", WITNESS_RANK_BASE))
return (true);
extent_tree_szad_new(&base_avail_szad);
base_extent_sn_next = 0;
extent_tree_szsnad_new(&base_avail_szsnad);
base_nodes = NULL;
return (false);

View File

@ -50,9 +50,9 @@ const chunk_hooks_t chunk_hooks_default = {
*/
static void chunk_record(tsdn_t *tsdn, arena_t *arena,
chunk_hooks_t *chunk_hooks, extent_tree_t *chunks_szad,
extent_tree_t *chunks_ad, bool cache, void *chunk, size_t size, bool zeroed,
bool committed);
chunk_hooks_t *chunk_hooks, extent_tree_t *chunks_szsnad,
extent_tree_t *chunks_ad, bool cache, void *chunk, size_t size, size_t sn,
bool zeroed, bool committed);
/******************************************************************************/
@ -183,33 +183,35 @@ chunk_deregister(const void *chunk, const extent_node_t *node)
}
/*
* Do first-best-fit chunk selection, i.e. select the lowest chunk that best
* fits.
* Do first-best-fit chunk selection, i.e. select the oldest/lowest chunk that
* best fits.
*/
static extent_node_t *
chunk_first_best_fit(arena_t *arena, extent_tree_t *chunks_szad,
extent_tree_t *chunks_ad, size_t size)
chunk_first_best_fit(arena_t *arena, extent_tree_t *chunks_szsnad, size_t size)
{
extent_node_t key;
assert(size == CHUNK_CEILING(size));
extent_node_init(&key, arena, NULL, size, false, false);
return (extent_tree_szad_nsearch(chunks_szad, &key));
extent_node_init(&key, arena, NULL, size, 0, false, false);
return (extent_tree_szsnad_nsearch(chunks_szsnad, &key));
}
static void *
chunk_recycle(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, bool cache,
void *new_addr, size_t size, size_t alignment, bool *zero, bool *commit,
bool dalloc_node)
extent_tree_t *chunks_szsnad, extent_tree_t *chunks_ad, bool cache,
void *new_addr, size_t size, size_t alignment, size_t *sn, bool *zero,
bool *commit, bool dalloc_node)
{
void *ret;
extent_node_t *node;
size_t alloc_size, leadsize, trailsize;
bool zeroed, committed;
assert(CHUNK_CEILING(size) == size);
assert(alignment > 0);
assert(new_addr == NULL || alignment == chunksize);
assert(CHUNK_ADDR2BASE(new_addr) == new_addr);
/*
* Cached chunks use the node linkage embedded in their headers, in
* which case dalloc_node is true, and new_addr is non-NULL because
@ -217,7 +219,7 @@ chunk_recycle(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
*/
assert(dalloc_node || new_addr != NULL);
alloc_size = CHUNK_CEILING(s2u(size + alignment - chunksize));
alloc_size = size + CHUNK_CEILING(alignment) - chunksize;
/* Beware size_t wrap-around. */
if (alloc_size < size)
return (NULL);
@ -225,12 +227,11 @@ chunk_recycle(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
chunk_hooks_assure_initialized_locked(tsdn, arena, chunk_hooks);
if (new_addr != NULL) {
extent_node_t key;
extent_node_init(&key, arena, new_addr, alloc_size, false,
extent_node_init(&key, arena, new_addr, alloc_size, 0, false,
false);
node = extent_tree_ad_search(chunks_ad, &key);
} else {
node = chunk_first_best_fit(arena, chunks_szad, chunks_ad,
alloc_size);
node = chunk_first_best_fit(arena, chunks_szsnad, alloc_size);
}
if (node == NULL || (new_addr != NULL && extent_node_size_get(node) <
size)) {
@ -243,6 +244,7 @@ chunk_recycle(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
assert(extent_node_size_get(node) >= leadsize + size);
trailsize = extent_node_size_get(node) - leadsize - size;
ret = (void *)((uintptr_t)extent_node_addr_get(node) + leadsize);
*sn = extent_node_sn_get(node);
zeroed = extent_node_zeroed_get(node);
if (zeroed)
*zero = true;
@ -257,13 +259,13 @@ chunk_recycle(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
return (NULL);
}
/* Remove node from the tree. */
extent_tree_szad_remove(chunks_szad, node);
extent_tree_szsnad_remove(chunks_szsnad, node);
extent_tree_ad_remove(chunks_ad, node);
arena_chunk_cache_maybe_remove(arena, node, cache);
if (leadsize != 0) {
/* Insert the leading space as a smaller chunk. */
extent_node_size_set(node, leadsize);
extent_tree_szad_insert(chunks_szad, node);
extent_tree_szsnad_insert(chunks_szsnad, node);
extent_tree_ad_insert(chunks_ad, node);
arena_chunk_cache_maybe_insert(arena, node, cache);
node = NULL;
@ -275,9 +277,9 @@ chunk_recycle(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
if (dalloc_node && node != NULL)
arena_node_dalloc(tsdn, arena, node);
malloc_mutex_unlock(tsdn, &arena->chunks_mtx);
chunk_record(tsdn, arena, chunk_hooks, chunks_szad,
chunks_ad, cache, ret, size + trailsize, zeroed,
committed);
chunk_record(tsdn, arena, chunk_hooks, chunks_szsnad,
chunks_ad, cache, ret, size + trailsize, *sn,
zeroed, committed);
return (NULL);
}
/* Insert the trailing space as a smaller chunk. */
@ -286,22 +288,22 @@ chunk_recycle(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
if (node == NULL) {
malloc_mutex_unlock(tsdn, &arena->chunks_mtx);
chunk_record(tsdn, arena, chunk_hooks,
chunks_szad, chunks_ad, cache, ret, size +
trailsize, zeroed, committed);
chunks_szsnad, chunks_ad, cache, ret, size
+ trailsize, *sn, zeroed, committed);
return (NULL);
}
}
extent_node_init(node, arena, (void *)((uintptr_t)(ret) + size),
trailsize, zeroed, committed);
extent_tree_szad_insert(chunks_szad, node);
trailsize, *sn, zeroed, committed);
extent_tree_szsnad_insert(chunks_szsnad, node);
extent_tree_ad_insert(chunks_ad, node);
arena_chunk_cache_maybe_insert(arena, node, cache);
node = NULL;
}
if (!committed && chunk_hooks->commit(ret, size, 0, size, arena->ind)) {
malloc_mutex_unlock(tsdn, &arena->chunks_mtx);
chunk_record(tsdn, arena, chunk_hooks, chunks_szad, chunks_ad,
cache, ret, size, zeroed, committed);
chunk_record(tsdn, arena, chunk_hooks, chunks_szsnad, chunks_ad,
cache, ret, size, *sn, zeroed, committed);
return (NULL);
}
malloc_mutex_unlock(tsdn, &arena->chunks_mtx);
@ -385,8 +387,8 @@ chunk_alloc_base(size_t size)
void *
chunk_alloc_cache(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
void *new_addr, size_t size, size_t alignment, bool *zero, bool *commit,
bool dalloc_node)
void *new_addr, size_t size, size_t alignment, size_t *sn, bool *zero,
bool *commit, bool dalloc_node)
{
void *ret;
@ -396,8 +398,8 @@ chunk_alloc_cache(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
assert((alignment & chunksize_mask) == 0);
ret = chunk_recycle(tsdn, arena, chunk_hooks,
&arena->chunks_szad_cached, &arena->chunks_ad_cached, true,
new_addr, size, alignment, zero, commit, dalloc_node);
&arena->chunks_szsnad_cached, &arena->chunks_ad_cached, true,
new_addr, size, alignment, sn, zero, commit, dalloc_node);
if (ret == NULL)
return (NULL);
if (config_valgrind)
@ -451,7 +453,8 @@ chunk_alloc_default(void *new_addr, size_t size, size_t alignment, bool *zero,
static void *
chunk_alloc_retained(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
void *new_addr, size_t size, size_t alignment, bool *zero, bool *commit)
void *new_addr, size_t size, size_t alignment, size_t *sn, bool *zero,
bool *commit)
{
void *ret;
@ -461,8 +464,8 @@ chunk_alloc_retained(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
assert((alignment & chunksize_mask) == 0);
ret = chunk_recycle(tsdn, arena, chunk_hooks,
&arena->chunks_szad_retained, &arena->chunks_ad_retained, false,
new_addr, size, alignment, zero, commit, true);
&arena->chunks_szsnad_retained, &arena->chunks_ad_retained, false,
new_addr, size, alignment, sn, zero, commit, true);
if (config_stats && ret != NULL)
arena->stats.retained -= size;
@ -472,14 +475,15 @@ chunk_alloc_retained(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
void *
chunk_alloc_wrapper(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
void *new_addr, size_t size, size_t alignment, bool *zero, bool *commit)
void *new_addr, size_t size, size_t alignment, size_t *sn, bool *zero,
bool *commit)
{
void *ret;
chunk_hooks_assure_initialized(tsdn, arena, chunk_hooks);
ret = chunk_alloc_retained(tsdn, arena, chunk_hooks, new_addr, size,
alignment, zero, commit);
alignment, sn, zero, commit);
if (ret == NULL) {
if (chunk_hooks->alloc == chunk_alloc_default) {
/* Call directly to propagate tsdn. */
@ -493,6 +497,8 @@ chunk_alloc_wrapper(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
if (ret == NULL)
return (NULL);
*sn = arena_extent_sn_next(arena);
if (config_valgrind && chunk_hooks->alloc !=
chunk_alloc_default)
JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, chunksize);
@ -503,8 +509,8 @@ chunk_alloc_wrapper(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
static void
chunk_record(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, bool cache,
void *chunk, size_t size, bool zeroed, bool committed)
extent_tree_t *chunks_szsnad, extent_tree_t *chunks_ad, bool cache,
void *chunk, size_t size, size_t sn, bool zeroed, bool committed)
{
bool unzeroed;
extent_node_t *node, *prev;
@ -516,7 +522,7 @@ chunk_record(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
malloc_mutex_lock(tsdn, &arena->chunks_mtx);
chunk_hooks_assure_initialized_locked(tsdn, arena, chunk_hooks);
extent_node_init(&key, arena, (void *)((uintptr_t)chunk + size), 0,
extent_node_init(&key, arena, (void *)((uintptr_t)chunk + size), 0, 0,
false, false);
node = extent_tree_ad_nsearch(chunks_ad, &key);
/* Try to coalesce forward. */
@ -528,15 +534,17 @@ chunk_record(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
/*
* Coalesce chunk with the following address range. This does
* not change the position within chunks_ad, so only
* remove/insert from/into chunks_szad.
* remove/insert from/into chunks_szsnad.
*/
extent_tree_szad_remove(chunks_szad, node);
extent_tree_szsnad_remove(chunks_szsnad, node);
arena_chunk_cache_maybe_remove(arena, node, cache);
extent_node_addr_set(node, chunk);
extent_node_size_set(node, size + extent_node_size_get(node));
if (sn < extent_node_sn_get(node))
extent_node_sn_set(node, sn);
extent_node_zeroed_set(node, extent_node_zeroed_get(node) &&
!unzeroed);
extent_tree_szad_insert(chunks_szad, node);
extent_tree_szsnad_insert(chunks_szsnad, node);
arena_chunk_cache_maybe_insert(arena, node, cache);
} else {
/* Coalescing forward failed, so insert a new node. */
@ -554,10 +562,10 @@ chunk_record(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
}
goto label_return;
}
extent_node_init(node, arena, chunk, size, !unzeroed,
extent_node_init(node, arena, chunk, size, sn, !unzeroed,
committed);
extent_tree_ad_insert(chunks_ad, node);
extent_tree_szad_insert(chunks_szad, node);
extent_tree_szsnad_insert(chunks_szsnad, node);
arena_chunk_cache_maybe_insert(arena, node, cache);
}
@ -571,19 +579,21 @@ chunk_record(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
/*
* Coalesce chunk with the previous address range. This does
* not change the position within chunks_ad, so only
* remove/insert node from/into chunks_szad.
* remove/insert node from/into chunks_szsnad.
*/
extent_tree_szad_remove(chunks_szad, prev);
extent_tree_szsnad_remove(chunks_szsnad, prev);
extent_tree_ad_remove(chunks_ad, prev);
arena_chunk_cache_maybe_remove(arena, prev, cache);
extent_tree_szad_remove(chunks_szad, node);
extent_tree_szsnad_remove(chunks_szsnad, node);
arena_chunk_cache_maybe_remove(arena, node, cache);
extent_node_addr_set(node, extent_node_addr_get(prev));
extent_node_size_set(node, extent_node_size_get(prev) +
extent_node_size_get(node));
if (extent_node_sn_get(prev) < extent_node_sn_get(node))
extent_node_sn_set(node, extent_node_sn_get(prev));
extent_node_zeroed_set(node, extent_node_zeroed_get(prev) &&
extent_node_zeroed_get(node));
extent_tree_szad_insert(chunks_szad, node);
extent_tree_szsnad_insert(chunks_szsnad, node);
arena_chunk_cache_maybe_insert(arena, node, cache);
arena_node_dalloc(tsdn, arena, prev);
@ -595,7 +605,7 @@ label_return:
void
chunk_dalloc_cache(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
void *chunk, size_t size, bool committed)
void *chunk, size_t size, size_t sn, bool committed)
{
assert(chunk != NULL);
@ -603,8 +613,9 @@ chunk_dalloc_cache(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
assert(size != 0);
assert((size & chunksize_mask) == 0);
chunk_record(tsdn, arena, chunk_hooks, &arena->chunks_szad_cached,
&arena->chunks_ad_cached, true, chunk, size, false, committed);
chunk_record(tsdn, arena, chunk_hooks, &arena->chunks_szsnad_cached,
&arena->chunks_ad_cached, true, chunk, size, sn, false,
committed);
arena_maybe_purge(tsdn, arena);
}
@ -627,7 +638,7 @@ chunk_dalloc_default(void *chunk, size_t size, bool committed,
void
chunk_dalloc_wrapper(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
void *chunk, size_t size, bool zeroed, bool committed)
void *chunk, size_t size, size_t sn, bool zeroed, bool committed)
{
bool err;
@ -653,8 +664,9 @@ chunk_dalloc_wrapper(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
}
zeroed = !committed || !chunk_hooks->purge(chunk, size, 0, size,
arena->ind);
chunk_record(tsdn, arena, chunk_hooks, &arena->chunks_szad_retained,
&arena->chunks_ad_retained, false, chunk, size, zeroed, committed);
chunk_record(tsdn, arena, chunk_hooks, &arena->chunks_szsnad_retained,
&arena->chunks_ad_retained, false, chunk, size, sn, zeroed,
committed);
if (config_stats)
arena->stats.retained += size;

View File

@ -162,7 +162,8 @@ chunk_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size,
CHUNK_HOOKS_INITIALIZER;
chunk_dalloc_wrapper(tsdn, arena,
&chunk_hooks, cpad, cpad_size,
false, true);
arena_extent_sn_next(arena), false,
true);
}
if (*zero) {
JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(

View File

@ -3,42 +3,45 @@
/******************************************************************************/
/*
* Round down to the nearest chunk size that can actually be requested during
* normal huge allocation.
*/
JEMALLOC_INLINE_C size_t
extent_quantize(size_t size)
{
size_t ret;
szind_t ind;
/*
* Round down to the nearest chunk size that can actually be requested
* during normal huge allocation.
*/
return (index2size(size2index(size + 1) - 1));
assert(size > 0);
ind = size2index(size + 1);
if (ind == 0) {
/* Avoid underflow. */
return (index2size(0));
}
JEMALLOC_INLINE_C int
extent_szad_comp(const extent_node_t *a, const extent_node_t *b)
{
int ret;
size_t a_qsize = extent_quantize(extent_node_size_get(a));
size_t b_qsize = extent_quantize(extent_node_size_get(b));
/*
* Compare based on quantized size rather than size, in order to sort
* equally useful extents only by address.
*/
ret = (a_qsize > b_qsize) - (a_qsize < b_qsize);
if (ret == 0) {
uintptr_t a_addr = (uintptr_t)extent_node_addr_get(a);
uintptr_t b_addr = (uintptr_t)extent_node_addr_get(b);
ret = (a_addr > b_addr) - (a_addr < b_addr);
}
ret = index2size(ind - 1);
assert(ret <= size);
return (ret);
}
/* Generate red-black tree functions. */
rb_gen(, extent_tree_szad_, extent_tree_t, extent_node_t, szad_link,
extent_szad_comp)
JEMALLOC_INLINE_C int
extent_sz_comp(const extent_node_t *a, const extent_node_t *b)
{
size_t a_qsize = extent_quantize(extent_node_size_get(a));
size_t b_qsize = extent_quantize(extent_node_size_get(b));
return ((a_qsize > b_qsize) - (a_qsize < b_qsize));
}
JEMALLOC_INLINE_C int
extent_sn_comp(const extent_node_t *a, const extent_node_t *b)
{
size_t a_sn = extent_node_sn_get(a);
size_t b_sn = extent_node_sn_get(b);
return ((a_sn > b_sn) - (a_sn < b_sn));
}
JEMALLOC_INLINE_C int
extent_ad_comp(const extent_node_t *a, const extent_node_t *b)
@ -49,5 +52,26 @@ extent_ad_comp(const extent_node_t *a, const extent_node_t *b)
return ((a_addr > b_addr) - (a_addr < b_addr));
}
JEMALLOC_INLINE_C int
extent_szsnad_comp(const extent_node_t *a, const extent_node_t *b)
{
int ret;
ret = extent_sz_comp(a, b);
if (ret != 0)
return (ret);
ret = extent_sn_comp(a, b);
if (ret != 0)
return (ret);
ret = extent_ad_comp(a, b);
return (ret);
}
/* Generate red-black tree functions. */
rb_gen(, extent_tree_szsnad_, extent_tree_t, extent_node_t, szsnad_link,
extent_szsnad_comp)
/* Generate red-black tree functions. */
rb_gen(, extent_tree_ad_, extent_tree_t, extent_node_t, ad_link, extent_ad_comp)

View File

@ -56,6 +56,7 @@ huge_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment,
size_t ausize;
arena_t *iarena;
extent_node_t *node;
size_t sn;
bool is_zeroed;
/* Allocate one or more contiguous chunks for this request. */
@ -68,7 +69,8 @@ huge_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment,
assert(ausize >= chunksize);
/* Allocate an extent node with which to track the chunk. */
iarena = (!tsdn_null(tsdn)) ? arena_ichoose(tsdn_tsd(tsdn), NULL) : a0get();
iarena = (!tsdn_null(tsdn)) ? arena_ichoose(tsdn_tsd(tsdn), NULL) :
a0get();
node = ipallocztm(tsdn, CACHELINE_CEILING(sizeof(extent_node_t)),
CACHELINE, false, NULL, true, iarena);
if (node == NULL)
@ -82,15 +84,15 @@ huge_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment,
if (likely(!tsdn_null(tsdn)))
arena = arena_choose(tsdn_tsd(tsdn), arena);
if (unlikely(arena == NULL) || (ret = arena_chunk_alloc_huge(tsdn,
arena, usize, alignment, &is_zeroed)) == NULL) {
arena, usize, alignment, &sn, &is_zeroed)) == NULL) {
idalloctm(tsdn, node, NULL, true, true);
return (NULL);
}
extent_node_init(node, arena, ret, usize, is_zeroed, true);
extent_node_init(node, arena, ret, usize, sn, is_zeroed, true);
if (huge_node_set(tsdn, ret, node)) {
arena_chunk_dalloc_huge(tsdn, arena, ret, usize);
arena_chunk_dalloc_huge(tsdn, arena, ret, usize, sn);
idalloctm(tsdn, node, NULL, true, true);
return (NULL);
}
@ -245,7 +247,8 @@ huge_ralloc_no_move_shrink(tsdn_t *tsdn, void *ptr, size_t oldsize,
malloc_mutex_unlock(tsdn, &arena->huge_mtx);
/* Zap the excess chunks. */
arena_chunk_ralloc_huge_shrink(tsdn, arena, ptr, oldsize, usize);
arena_chunk_ralloc_huge_shrink(tsdn, arena, ptr, oldsize, usize,
extent_node_sn_get(node));
return (false);
}
@ -407,7 +410,8 @@ huge_dalloc(tsdn_t *tsdn, void *ptr)
huge_dalloc_junk(extent_node_addr_get(node),
extent_node_size_get(node));
arena_chunk_dalloc_huge(tsdn, extent_node_arena_get(node),
extent_node_addr_get(node), extent_node_size_get(node));
extent_node_addr_get(node), extent_node_size_get(node),
extent_node_sn_get(node));
idalloctm(tsdn, node, NULL, true, true);
arena_decay_tick(tsdn, arena);

View File

@ -1060,7 +1060,11 @@ malloc_conf_init(void)
if (cont) \
continue; \
}
#define CONF_HANDLE_T_U(t, o, n, min, max, clip) \
#define CONF_MIN_no(um, min) false
#define CONF_MIN_yes(um, min) ((um) < (min))
#define CONF_MAX_no(um, max) false
#define CONF_MAX_yes(um, max) ((um) > (max))
#define CONF_HANDLE_T_U(t, o, n, min, max, check_min, check_max, clip) \
if (CONF_MATCH(n)) { \
uintmax_t um; \
char *end; \
@ -1073,15 +1077,19 @@ malloc_conf_init(void)
"Invalid conf value", \
k, klen, v, vlen); \
} else if (clip) { \
if ((min) != 0 && um < (min)) \
if (CONF_MIN_##check_min(um, \
(min))) \
o = (t)(min); \
else if (um > (max)) \
else if (CONF_MAX_##check_max( \
um, (max))) \
o = (t)(max); \
else \
o = (t)um; \
} else { \
if (((min) != 0 && um < (min)) \
|| um > (max)) { \
if (CONF_MIN_##check_min(um, \
(min)) || \
CONF_MAX_##check_max(um, \
(max))) { \
malloc_conf_error( \
"Out-of-range " \
"conf value", \
@ -1091,10 +1099,13 @@ malloc_conf_init(void)
} \
continue; \
}
#define CONF_HANDLE_UNSIGNED(o, n, min, max, clip) \
CONF_HANDLE_T_U(unsigned, o, n, min, max, clip)
#define CONF_HANDLE_SIZE_T(o, n, min, max, clip) \
CONF_HANDLE_T_U(size_t, o, n, min, max, clip)
#define CONF_HANDLE_UNSIGNED(o, n, min, max, check_min, check_max, \
clip) \
CONF_HANDLE_T_U(unsigned, o, n, min, max, \
check_min, check_max, clip)
#define CONF_HANDLE_SIZE_T(o, n, min, max, check_min, check_max, clip) \
CONF_HANDLE_T_U(size_t, o, n, min, max, \
check_min, check_max, clip)
#define CONF_HANDLE_SSIZE_T(o, n, min, max) \
if (CONF_MATCH(n)) { \
long l; \
@ -1137,7 +1148,7 @@ malloc_conf_init(void)
*/
CONF_HANDLE_SIZE_T(opt_lg_chunk, "lg_chunk", LG_PAGE +
LG_SIZE_CLASS_GROUP + (config_fill ? 2 : 1),
(sizeof(size_t) << 3) - 1, true)
(sizeof(size_t) << 3) - 1, yes, yes, true)
if (strncmp("dss", k, klen) == 0) {
int i;
bool match = false;
@ -1163,7 +1174,7 @@ malloc_conf_init(void)
continue;
}
CONF_HANDLE_UNSIGNED(opt_narenas, "narenas", 1,
UINT_MAX, false)
UINT_MAX, yes, no, false)
if (strncmp("purge", k, klen) == 0) {
int i;
bool match = false;
@ -1234,7 +1245,7 @@ malloc_conf_init(void)
continue;
}
CONF_HANDLE_SIZE_T(opt_quarantine, "quarantine",
0, SIZE_T_MAX, false)
0, SIZE_T_MAX, no, no, false)
CONF_HANDLE_BOOL(opt_redzone, "redzone", true)
CONF_HANDLE_BOOL(opt_zero, "zero", true)
}
@ -1271,8 +1282,8 @@ malloc_conf_init(void)
CONF_HANDLE_BOOL(opt_prof_thread_active_init,
"prof_thread_active_init", true)
CONF_HANDLE_SIZE_T(opt_lg_prof_sample,
"lg_prof_sample", 0,
(sizeof(uint64_t) << 3) - 1, true)
"lg_prof_sample", 0, (sizeof(uint64_t) << 3)
- 1, no, yes, true)
CONF_HANDLE_BOOL(opt_prof_accum, "prof_accum",
true)
CONF_HANDLE_SSIZE_T(opt_lg_prof_interval,
@ -1288,7 +1299,14 @@ malloc_conf_init(void)
malloc_conf_error("Invalid conf pair", k, klen, v,
vlen);
#undef CONF_MATCH
#undef CONF_MATCH_VALUE
#undef CONF_HANDLE_BOOL
#undef CONF_MIN_no
#undef CONF_MIN_yes
#undef CONF_MAX_no
#undef CONF_MAX_yes
#undef CONF_HANDLE_T_U
#undef CONF_HANDLE_UNSIGNED
#undef CONF_HANDLE_SIZE_T
#undef CONF_HANDLE_SSIZE_T
#undef CONF_HANDLE_CHAR_P
@ -1397,8 +1415,9 @@ malloc_init_hard_recursible(void)
ncpus = malloc_ncpus();
#if (!defined(JEMALLOC_MUTEX_INIT_CB) && !defined(JEMALLOC_ZONE) \
&& !defined(_WIN32) && !defined(__native_client__))
#if (defined(JEMALLOC_HAVE_PTHREAD_ATFORK) && !defined(JEMALLOC_MUTEX_INIT_CB) \
&& !defined(JEMALLOC_ZONE) && !defined(_WIN32) && \
!defined(__native_client__))
/* LinuxThreads' pthread_atfork() allocates. */
if (pthread_atfork(jemalloc_prefork, jemalloc_postfork_parent,
jemalloc_postfork_child) != 0) {
@ -1977,8 +1996,8 @@ je_realloc(void *ptr, size_t size)
*tsd_thread_deallocatedp_get(tsd) += old_usize;
}
UTRACE(ptr, size, ret);
JEMALLOC_VALGRIND_REALLOC(true, tsdn, ret, usize, true, ptr, old_usize,
old_rzsize, true, false);
JEMALLOC_VALGRIND_REALLOC(maybe, tsdn, ret, usize, maybe, ptr,
old_usize, old_rzsize, maybe, false);
witness_assert_lockless(tsdn);
return (ret);
}
@ -2404,8 +2423,8 @@ je_rallocx(void *ptr, size_t size, int flags)
*tsd_thread_deallocatedp_get(tsd) += old_usize;
}
UTRACE(ptr, size, p);
JEMALLOC_VALGRIND_REALLOC(true, tsd_tsdn(tsd), p, usize, false, ptr,
old_usize, old_rzsize, false, zero);
JEMALLOC_VALGRIND_REALLOC(maybe, tsd_tsdn(tsd), p, usize, no, ptr,
old_usize, old_rzsize, no, zero);
witness_assert_lockless(tsd_tsdn(tsd));
return (p);
label_oom:
@ -2547,8 +2566,8 @@ je_xallocx(void *ptr, size_t size, size_t extra, int flags)
*tsd_thread_allocatedp_get(tsd) += usize;
*tsd_thread_deallocatedp_get(tsd) += old_usize;
}
JEMALLOC_VALGRIND_REALLOC(false, tsd_tsdn(tsd), ptr, usize, false, ptr,
old_usize, old_rzsize, false, zero);
JEMALLOC_VALGRIND_REALLOC(no, tsd_tsdn(tsd), ptr, usize, no, ptr,
old_usize, old_rzsize, no, zero);
label_not_resized:
UTRACE(ptr, size, ptr);
witness_assert_lockless(tsd_tsdn(tsd));

View File

@ -170,15 +170,16 @@ pages_purge(void *addr, size_t size)
#ifdef _WIN32
VirtualAlloc(addr, size, MEM_RESET, PAGE_READWRITE);
unzeroed = true;
#elif defined(JEMALLOC_HAVE_MADVISE)
# ifdef JEMALLOC_PURGE_MADVISE_DONTNEED
# define JEMALLOC_MADV_PURGE MADV_DONTNEED
# define JEMALLOC_MADV_ZEROS true
# elif defined(JEMALLOC_PURGE_MADVISE_FREE)
#elif (defined(JEMALLOC_PURGE_MADVISE_FREE) || \
defined(JEMALLOC_PURGE_MADVISE_DONTNEED))
# if defined(JEMALLOC_PURGE_MADVISE_FREE)
# define JEMALLOC_MADV_PURGE MADV_FREE
# define JEMALLOC_MADV_ZEROS false
# elif defined(JEMALLOC_PURGE_MADVISE_DONTNEED)
# define JEMALLOC_MADV_PURGE MADV_DONTNEED
# define JEMALLOC_MADV_ZEROS true
# else
# error "No madvise(2) flag defined for purging unused dirty pages."
# error No madvise(2) flag defined for purging unused dirty pages
# endif
int err = madvise(addr, size, JEMALLOC_MADV_PURGE);
unzeroed = (!JEMALLOC_MADV_ZEROS || err != 0);
@ -191,6 +192,34 @@ pages_purge(void *addr, size_t size)
return (unzeroed);
}
bool
pages_huge(void *addr, size_t size)
{
assert(PAGE_ADDR2BASE(addr) == addr);
assert(PAGE_CEILING(size) == size);
#ifdef JEMALLOC_THP
return (madvise(addr, size, MADV_HUGEPAGE) != 0);
#else
return (false);
#endif
}
bool
pages_nohuge(void *addr, size_t size)
{
assert(PAGE_ADDR2BASE(addr) == addr);
assert(PAGE_CEILING(size) == size);
#ifdef JEMALLOC_THP
return (madvise(addr, size, MADV_NOHUGEPAGE) != 0);
#else
return (false);
#endif
}
#ifdef JEMALLOC_SYSCTL_VM_OVERCOMMIT
static bool
os_overcommits_sysctl(void)
@ -219,7 +248,7 @@ os_overcommits_proc(void)
char buf[1];
ssize_t nread;
#if defined(JEMALLOC_HAVE_SYSCALL) && defined(SYS_open)
#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_open)
fd = (int)syscall(SYS_open, "/proc/sys/vm/overcommit_memory", O_RDONLY);
#else
fd = open("/proc/sys/vm/overcommit_memory", O_RDONLY);
@ -227,13 +256,13 @@ os_overcommits_proc(void)
if (fd == -1)
return (false); /* Error. */
#if defined(JEMALLOC_HAVE_SYSCALL) && defined(SYS_read)
#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_read)
nread = (ssize_t)syscall(SYS_read, fd, &buf, sizeof(buf));
#else
nread = read(fd, &buf, sizeof(buf));
#endif
#if defined(JEMALLOC_HAVE_SYSCALL) && defined(SYS_close)
#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_close)
syscall(SYS_close, fd);
#else
close(fd);

View File

@ -3,7 +3,7 @@
#define CTL_GET(n, v, t) do { \
size_t sz = sizeof(t); \
xmallctl(n, v, &sz, NULL, 0); \
xmallctl(n, (void *)v, &sz, NULL, 0); \
} while (0)
#define CTL_M2_GET(n, i, v, t) do { \
@ -12,7 +12,7 @@
size_t sz = sizeof(t); \
xmallctlnametomib(n, mib, &miblen); \
mib[2] = (i); \
xmallctlbymib(mib, miblen, v, &sz, NULL, 0); \
xmallctlbymib(mib, miblen, (void *)v, &sz, NULL, 0); \
} while (0)
#define CTL_M2_M4_GET(n, i, j, v, t) do { \
@ -22,7 +22,7 @@
xmallctlnametomib(n, mib, &miblen); \
mib[2] = (i); \
mib[4] = (j); \
xmallctlbymib(mib, miblen, v, &sz, NULL, 0); \
xmallctlbymib(mib, miblen, (void *)v, &sz, NULL, 0); \
} while (0)
/******************************************************************************/
@ -647,7 +647,7 @@ stats_general_print(void (*write_cb)(void *, const char *), void *cbopaque,
#define OPT_WRITE_BOOL_MUTABLE(n, m, c) { \
bool bv2; \
if (je_mallctl("opt."#n, (void *)&bv, &bsz, NULL, 0) == 0 && \
je_mallctl(#m, &bv2, &bsz, NULL, 0) == 0) { \
je_mallctl(#m, &bv2, (void *)&bsz, NULL, 0) == 0) { \
if (json) { \
malloc_cprintf(write_cb, cbopaque, \
"\t\t\t\""#n"\": %s%s\n", bv ? "true" : \
@ -692,7 +692,7 @@ stats_general_print(void (*write_cb)(void *, const char *), void *cbopaque,
#define OPT_WRITE_SSIZE_T_MUTABLE(n, m, c) { \
ssize_t ssv2; \
if (je_mallctl("opt."#n, (void *)&ssv, &sssz, NULL, 0) == 0 && \
je_mallctl(#m, &ssv2, &sssz, NULL, 0) == 0) { \
je_mallctl(#m, (void *)&ssv2, &sssz, NULL, 0) == 0) { \
if (json) { \
malloc_cprintf(write_cb, cbopaque, \
"\t\t\t\""#n"\": %zd%s\n", ssv, (c)); \
@ -1084,7 +1084,8 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
* */
epoch = 1;
u64sz = sizeof(uint64_t);
err = je_mallctl("epoch", &epoch, &u64sz, &epoch, sizeof(uint64_t));
err = je_mallctl("epoch", (void *)&epoch, &u64sz, (void *)&epoch,
sizeof(uint64_t));
if (err != 0) {
if (err == EAGAIN) {
malloc_write("<jemalloc>: Memory allocation failure in "

View File

@ -517,12 +517,12 @@ tcache_boot(tsdn_t *tsdn)
* If necessary, clamp opt_lg_tcache_max, now that large_maxclass is
* known.
*/
if (opt_lg_tcache_max < 0 || (1U << opt_lg_tcache_max) < SMALL_MAXCLASS)
if (opt_lg_tcache_max < 0 || (ZU(1) << opt_lg_tcache_max) < SMALL_MAXCLASS)
tcache_maxclass = SMALL_MAXCLASS;
else if ((1U << opt_lg_tcache_max) > large_maxclass)
else if ((ZU(1) << opt_lg_tcache_max) > large_maxclass)
tcache_maxclass = large_maxclass;
else
tcache_maxclass = (1U << opt_lg_tcache_max);
tcache_maxclass = (ZU(1) << opt_lg_tcache_max);
nhbins = size2index(tcache_maxclass) + 1;

View File

@ -49,7 +49,7 @@ static void
wrtmessage(void *cbopaque, const char *s)
{
#if defined(JEMALLOC_HAVE_SYSCALL) && defined(SYS_write)
#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_write)
/*
* Use syscall(2) rather than write(2) when possible in order to avoid
* the possibility of memory allocation within libc. This is necessary
@ -216,7 +216,7 @@ malloc_strtoumax(const char *restrict nptr, char **restrict endptr, int base)
p++;
}
if (neg)
ret = -ret;
ret = (uintmax_t)(-((intmax_t)ret));
if (p == ns) {
/* No conversion performed. */

View File

@ -520,7 +520,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
return (0); /* Standard: return 0 for end-of-string. */
cnt = utf8_count[ch];
/* Invalide sequence or there are not plenty bytes. */
/* Invalid sequence or there are not plenty bytes. */
if (n < (size_t)cnt)
return (-1);
@ -559,7 +559,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
return (-1);
}
/* The code point larger than 0x10FFFF is not leagal
/* The code point larger than 0x10FFFF is not legal
* Unicode values. */
if (wc > 0x10FFFF)
return (-1);

View File

@ -521,7 +521,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
return (0); /* Standard: return 0 for end-of-string. */
cnt = utf8_count[ch];
/* Invalide sequence or there are not plenty bytes. */
/* Invalid sequence or there are not plenty bytes. */
if (n < (size_t)cnt)
return (-1);
@ -560,7 +560,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
return (-1);
}
/* The code point larger than 0x10FFFF is not leagal
/* The code point larger than 0x10FFFF is not legal
* Unicode values. */
if (wc > 0x10FFFF)
return (-1);

View File

@ -690,7 +690,7 @@ translate_acl(struct archive_read_disk *a,
#ifdef ACL_TYPE_NFS4
if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
/*
* acl_get_entry_type_np() falis with non-NFSv4 ACLs
* acl_get_entry_type_np() fails with non-NFSv4 ACLs
*/
if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) {
archive_set_error(&a->archive, errno, "Failed "
@ -1194,7 +1194,7 @@ setup_sparse_fiemap(struct archive_read_disk *a,
if (r < 0) {
/* When something error happens, it is better we
* should return ARCHIVE_OK because an earlier
* version(<2.6.28) cannot perfom FS_IOC_FIEMAP. */
* version(<2.6.28) cannot perform FS_IOC_FIEMAP. */
goto exit_setup_sparse_fiemap;
}
if (fm->fm_mapped_extents == 0) {
@ -1354,7 +1354,7 @@ setup_sparse(struct archive_read_disk *a,
goto exit_setup_sparse;
}
if (off_s == 0 && off_e == size)
break;/* This is not spase. */
break;/* This is not sparse. */
archive_entry_sparse_add_entry(entry, off_s,
off_e - off_s);
off_s = off_e;

View File

@ -511,6 +511,13 @@ read_more:
}
llen = len;
if ((nl == 0) && (uudecode->state != ST_UUEND)) {
if (total == 0 && ravail <= 0) {
/* There is nothing more to read, fail */
archive_set_error(&self->archive->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Missing format data");
return (ARCHIVE_FATAL);
}
/*
* Save remaining data which does not contain
* NL('\n','\r').
@ -567,7 +574,7 @@ read_more:
"Insufficient compressed data");
return (ARCHIVE_FATAL);
}
/* Get length of undecoded bytes of curent line. */
/* Get length of undecoded bytes of current line. */
l = UUDECODE(*b++);
body--;
if (l > body) {

View File

@ -260,7 +260,7 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry,
archive_entry_set_filetype(entry, AE_IFREG);
/* Get the size of the filename table. */
number = ar_atol10(h + AR_size_offset, AR_size_size);
if (number > SIZE_MAX) {
if (number > SIZE_MAX || number > 1024 * 1024 * 1024) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Filename table too large");
return (ARCHIVE_FATAL);
@ -342,16 +342,19 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry,
/* Parse the size of the name, adjust the file size. */
number = ar_atol10(h + AR_name_offset + 3, AR_name_size - 3);
bsd_name_length = (size_t)number;
/* Guard against the filename + trailing NUL
* overflowing a size_t and against the filename size
* being larger than the entire entry. */
if (number > (uint64_t)(bsd_name_length + 1)
|| (int64_t)bsd_name_length > ar->entry_bytes_remaining) {
/* Sanity check the filename length:
* = Must be <= SIZE_MAX - 1
* = Must be <= 1MB
* = Cannot be bigger than the entire entry
*/
if (number > SIZE_MAX - 1
|| number > 1024 * 1024
|| (int64_t)number > ar->entry_bytes_remaining) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Bad input file size");
return (ARCHIVE_FATAL);
}
bsd_name_length = (size_t)number;
ar->entry_bytes_remaining -= bsd_name_length;
/* Adjust file size reported to client. */
archive_entry_set_size(entry, ar->entry_bytes_remaining);

View File

@ -67,7 +67,7 @@ struct lzx_dec {
/* The length how many bytes we can copy decoded code from
* the window. */
int copy_len;
/* Translation reversal for x86 proccessor CALL byte sequence(E8).
/* Translation reversal for x86 processor CALL byte sequence(E8).
* This is used for LZX only. */
uint32_t translation_size;
char translation;
@ -1555,7 +1555,7 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
/*
* Note: I suspect there is a bug in makecab.exe because, in rare
* case, compressed bytes are still remaining regardless we have
* gotten all uncompressed bytes, which size is recoded in CFDATA,
* gotten all uncompressed bytes, which size is recorded in CFDATA,
* as much as we need, and we have to use the garbage so as to
* correctly compute the sum of CFDATA accordingly.
*/
@ -1742,7 +1742,7 @@ cab_read_ahead_cfdata_lzx(struct archive_read *a, ssize_t *avail)
}
/*
* Translation reversal of x86 proccessor CALL byte sequence(E8).
* Translation reversal of x86 processor CALL byte sequence(E8).
*/
lzx_translation(&cab->xstrm, cab->uncompressed_buffer,
cfdata->uncompressed_size,
@ -2271,7 +2271,7 @@ static int
lzx_br_fillup(struct lzx_stream *strm, struct lzx_br *br)
{
/*
* x86 proccessor family can read misaligned data without an access error.
* x86 processor family can read misaligned data without an access error.
*/
int n = CACHE_BITS - br->cache_avail;

View File

@ -299,14 +299,21 @@ archive_read_format_tar_cleanup(struct archive_read *a)
*
* This has to be pretty lenient in order to accomodate the enormous
* variety of tar writers in the world:
* = POSIX ustar requires octal values with leading zeros and
* specific termination on fields
* = POSIX (IEEE Std 1003.1-1988) ustar requires octal values with leading
* zeros and allows fields to be terminated with space or null characters
* = Many writers use different termination (in particular, libarchive
* omits terminator bytes to squeeze one or two more digits)
* = Many writers pad with space and omit leading zeros
* = GNU tar and star write base-256 values if numbers are too
* big to be represented in octal
*
* Examples of specific tar headers that we should support:
* = Perl Archive::Tar terminates uid, gid, devminor and devmajor with two
* null bytes, pads size with spaces and other numeric fields with zeroes
* = plexus-archiver prior to 2.6.3 (before switching to commons-compress)
* may have uid and gid fields filled with spaces without any octal digits
* at all and pads all numeric fields with spaces
*
* This should tolerate all variants in use. It will reject a field
* where the writer just left garbage after a trailing NUL.
*/
@ -324,11 +331,7 @@ validate_number_field(const char* p_field, size_t i_size)
while (i < i_size && p_field[i] == ' ') {
++i;
}
/* Must be at least one octal digit. */
if (i >= i_size || p_field[i] < '0' || p_field[i] > '7') {
return 0;
}
/* Skip remaining octal digits. */
/* Skip octal digits. */
while (i < i_size && p_field[i] >= '0' && p_field[i] <= '7') {
++i;
}

View File

@ -2298,7 +2298,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
return (0); /* Standard: return 0 for end-of-string. */
cnt = utf8_count[ch];
/* Invalide sequence or there are not plenty bytes. */
/* Invalid sequence or there are not plenty bytes. */
if ((int)n < cnt) {
cnt = (int)n;
for (i = 1; i < cnt; i++) {
@ -2379,7 +2379,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
goto invalid_sequence;
}
/* The code point larger than 0x10FFFF is not leagal
/* The code point larger than 0x10FFFF is not legal
* Unicode values. */
if (wc > UNICODE_MAX)
goto invalid_sequence;
@ -2397,7 +2397,7 @@ utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
int cnt;
cnt = _utf8_to_unicode(pwc, s, n);
/* Any of Surrogate pair is not leagal Unicode values. */
/* Any of Surrogate pair is not legal Unicode values. */
if (cnt == 3 && IS_SURROGATE_PAIR_LA(*pwc))
return (-3);
return (cnt);
@ -2458,7 +2458,7 @@ invalid_sequence:
/*
* Convert a Unicode code point to a single UTF-8 sequence.
*
* NOTE:This function does not check if the Unicode is leagal or not.
* NOTE:This function does not check if the Unicode is legal or not.
* Please you definitely check it before calling this.
*/
static size_t
@ -2554,7 +2554,7 @@ utf16_to_unicode(uint32_t *pwc, const char *s, size_t n, int be)
* Surrogate pair values(0xd800 through 0xdfff) are only
* used by UTF-16, so, after above culculation, the code
* must not be surrogate values, and Unicode has no codes
* larger than 0x10ffff. Thus, those are not leagal Unicode
* larger than 0x10ffff. Thus, those are not legal Unicode
* values.
*/
if (IS_SURROGATE_PAIR_LA(uc) || uc > UNICODE_MAX) {

View File

@ -115,13 +115,13 @@ archive_string_conversion_set_opt(struct archive_string_conv *, int);
/* Copy one archive_string to another in locale conversion.
* Return -1 if conversion failes. */
* Return -1 if conversion fails. */
int
archive_strncpy_l(struct archive_string *, const void *, size_t,
struct archive_string_conv *);
/* Copy one archive_string to another in locale conversion.
* Return -1 if conversion failes. */
* Return -1 if conversion fails. */
int
archive_strncat_l(struct archive_string *, const void *, size_t,
struct archive_string_conv *);

View File

@ -205,7 +205,7 @@ struct _7zip {
/*
* The list of the file entries which has its contents is used to
* manage struct file objects.
* We use 'next' a menber of struct file to chain.
* We use 'next' (a member of struct file) to chain.
*/
struct {
struct file *first;

View File

@ -289,7 +289,7 @@ write_header(struct archive_write *a, struct archive_entry *entry)
sconv = get_sconv(a);
#if defined(_WIN32) && !defined(__CYGWIN__)
/* Make sure the path separators in pahtname, hardlink and symlink
/* Make sure the path separators in pathname, hardlink and symlink
* are all slash '/', not the Windows path separator '\'. */
entry_main = __la_win_entry_in_posix_pathseparator(entry);
if (entry_main == NULL) {

View File

@ -232,7 +232,7 @@ write_header(struct archive_write *a, struct archive_entry *entry)
sconv = get_sconv(a);
#if defined(_WIN32) && !defined(__CYGWIN__)
/* Make sure the path separators in pahtname, hardlink and symlink
/* Make sure the path separators in pathname, hardlink and symlink
* are all slash '/', not the Windows path separator '\'. */
entry_main = __la_win_entry_in_posix_pathseparator(entry);
if (entry_main == NULL) {

View File

@ -119,9 +119,9 @@ static const char template_header[] = {
'0','0','0','0','0','0', '0','\0',
/* gid, null termination: 8 bytes */
'0','0','0','0','0','0', '0','\0',
/* size, space termation: 12 bytes */
/* size, space termination: 12 bytes */
'0','0','0','0','0','0','0','0','0','0','0', '\0',
/* mtime, space termation: 12 bytes */
/* mtime, space termination: 12 bytes */
'0','0','0','0','0','0','0','0','0','0','0', '\0',
/* Initial checksum value: 8 spaces */
' ',' ',' ',' ',' ',' ',' ',' ',
@ -368,7 +368,7 @@ archive_write_gnutar_header(struct archive_write *a,
}
#if defined(_WIN32) && !defined(__CYGWIN__)
/* Make sure the path separators in pahtname, hardlink and symlink
/* Make sure the path separators in pathname, hardlink and symlink
* are all slash '/', not the Windows path separator '\'. */
entry_main = __la_win_entry_in_posix_pathseparator(entry);
if (entry_main == NULL) {

View File

@ -1840,9 +1840,9 @@ mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file,
len = strlen(p);
/*
* Add "./" prefiex.
* Add "./" prefix.
* NOTE: If the pathname does not have a path separator, we have
* to add "./" to the head of the pathename because mtree reader
* to add "./" to the head of the pathname because mtree reader
* will suppose that it is v1(a.k.a classic) mtree format and
* change the directory unexpectedly and so it will make a wrong
* path.

View File

@ -709,7 +709,7 @@ archive_write_pax_header(struct archive_write *a,
/* Copy entry so we can modify it as needed. */
#if defined(_WIN32) && !defined(__CYGWIN__)
/* Make sure the path separators in pahtname, hardlink and symlink
/* Make sure the path separators in pathname, hardlink and symlink
* are all slash '/', not the Windows path separator '\'. */
entry_main = __la_win_entry_in_posix_pathseparator(entry_original);
if (entry_main == entry_original)

View File

@ -114,9 +114,9 @@ static const char template_header[] = {
'0','0','0','0','0','0', ' ','\0',
/* gid, space-null termination: 8 bytes */
'0','0','0','0','0','0', ' ','\0',
/* size, space termation: 12 bytes */
/* size, space termination: 12 bytes */
'0','0','0','0','0','0','0','0','0','0','0', ' ',
/* mtime, space termation: 12 bytes */
/* mtime, space termination: 12 bytes */
'0','0','0','0','0','0','0','0','0','0','0', ' ',
/* Initial checksum value: 8 spaces */
' ',' ',' ',' ',' ',' ',' ',' ',
@ -336,7 +336,7 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
}
#if defined(_WIN32) && !defined(__CYGWIN__)
/* Make sure the path separators in pahtname, hardlink and symlink
/* Make sure the path separators in pathname, hardlink and symlink
* are all slash '/', not the Windows path separator '\'. */
entry_main = __la_win_entry_in_posix_pathseparator(entry);
if (entry_main == NULL) {

View File

@ -98,9 +98,9 @@ static const char template_header[] = {
'0','0','0','0','0','0', ' ','\0',
/* gid, space-null termination: 8 bytes */
'0','0','0','0','0','0', ' ','\0',
/* size, space termation: 12 bytes */
/* size, space termination: 12 bytes */
'0','0','0','0','0','0','0','0','0','0','0', ' ',
/* mtime, space termation: 12 bytes */
/* mtime, space termination: 12 bytes */
'0','0','0','0','0','0','0','0','0','0','0', ' ',
/* Initial checksum value: 8 spaces */
' ',' ',' ',' ',' ',' ',' ',' ',
@ -314,7 +314,7 @@ archive_write_v7tar_header(struct archive_write *a, struct archive_entry *entry)
}
#if defined(_WIN32) && !defined(__CYGWIN__)
/* Make sure the path separators in pahtname, hardlink and symlink
/* Make sure the path separators in pathname, hardlink and symlink
* are all slash '/', not the Windows path separator '\'. */
entry_main = __la_win_entry_in_posix_pathseparator(entry);
if (entry_main == NULL) {

View File

@ -592,7 +592,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
#if defined(_WIN32) && !defined(__CYGWIN__)
/* Make sure the path separators in pahtname, hardlink and symlink
/* Make sure the path separators in pathname, hardlink and symlink
* are all slash '/', not the Windows path separator '\'. */
zip->entry = __la_win_entry_in_posix_pathseparator(entry);
if (zip->entry == entry)

View File

@ -519,7 +519,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
return (0); /* Standard: return 0 for end-of-string. */
cnt = utf8_count[ch];
/* Invalide sequence or there are not plenty bytes. */
/* Invalid sequence or there are not plenty bytes. */
if (n < (size_t)cnt)
return (-1);
@ -558,7 +558,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n)
return (-1);
}
/* The code point larger than 0x10FFFF is not leagal
/* The code point larger than 0x10FFFF is not legal
* Unicode values. */
if (wc > 0x10FFFF)
return (-1);

View File

@ -66,7 +66,7 @@ DEFINE_TEST(test_archive_cmdline)
assertEqualString("gzip", cl->argv[0]);
assertEqualInt(ARCHIVE_OK, __archive_cmdline_free(cl));
/* A command line includes space characer. */
/* A command line includes space character. */
assert((cl = __archive_cmdline_allocate()) != NULL);
if (cl == NULL)
return;
@ -78,7 +78,7 @@ DEFINE_TEST(test_archive_cmdline)
assertEqualString("gzip ", cl->argv[0]);
assertEqualInt(ARCHIVE_OK, __archive_cmdline_free(cl));
/* A command line includes space characer: pattern 2.*/
/* A command line includes space character: pattern 2.*/
assert((cl = __archive_cmdline_allocate()) != NULL);
if (cl == NULL)
return;
@ -90,7 +90,7 @@ DEFINE_TEST(test_archive_cmdline)
assertEqualString("gzip x", cl->argv[0]);
assertEqualInt(ARCHIVE_OK, __archive_cmdline_free(cl));
/* A command line includes space characer: pattern 3.*/
/* A command line includes space character: pattern 3.*/
assert((cl = __archive_cmdline_allocate()) != NULL);
if (cl == NULL)
return;
@ -103,7 +103,7 @@ DEFINE_TEST(test_archive_cmdline)
assertEqualString("gzip x s ", cl->argv[0]);
assertEqualInt(ARCHIVE_OK, __archive_cmdline_free(cl));
/* A command line includes space characer: pattern 4.*/
/* A command line includes space character: pattern 4.*/
assert((cl = __archive_cmdline_allocate()) != NULL);
if (cl == NULL)
return;

View File

@ -0,0 +1,69 @@
/*-
* Copyright (c) 2016 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
__FBSDID("$FreeBSD");
/*
* Verify our ability to read sample files created by plexus-archiver version
* 2.6.2 and lower (project switched to Apache Commons Compress with 2.6.3).
*
* These files may have tar entries with uid and gid header fields filled with
* spaces without any octal digit.
*/
DEFINE_TEST(test_compat_plexus_archiver_tar)
{
char name[] = "test_compat_plexus_archiver_tar.tar";
struct archive_entry *ae;
struct archive *a;
int r;
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
extract_reference_file(name);
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name,
10240));
/* Read first entry. */
assertEqualIntA(a, ARCHIVE_OK, r = archive_read_next_header(a, &ae));
if (r != ARCHIVE_OK) {
archive_read_free(a);
return;
}
assertEqualString("commons-logging-1.2/NOTICE.txt",
archive_entry_pathname(ae));
assertEqualInt(1404583896, archive_entry_mtime(ae));
assertEqualInt(0100664, archive_entry_mode(ae));
assertEqualInt(0, archive_entry_uid(ae));
assertEqualInt(0, archive_entry_gid(ae));
/* Verify that the format detection worked. */
assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE);
assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR);
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}

View File

@ -0,0 +1,49 @@
begin 644 test_compat_plexus_archiver_tar.tar
M8V]M;6]N<RUL;V=G:6YG+3$N,B].3U1)0T4N='AT````````````````````
M````````````````````````````````````````````````````````````
M`````````````#$P,#8V-"``("`@("`@(``@("`@("`@`"`@("`@("`@,C8Q
M(#$R,S4V,#,W-S,P("`Q-#$U-P`@,```````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````````````````````````!U<W1A<@```'1N````
M````````````````````````````````````=&X`````````````````````
M```````````````````@("`@(#`@`"`@("`@,"``````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M``````````````````````!!<&%C:&4@0V]M;6]N<R!,;V=G:6YG"D-O<'ER
M:6=H="`R,#`S+3(P,30@5&AE($%P86-H92!3;V9T=V%R92!&;W5N9&%T:6]N
M"@I4:&ES('!R;V1U8W0@:6YC;'5D97,@<V]F='=A<F4@9&5V96QO<&5D(&%T
M"E1H92!!<&%C:&4@4V]F='=A<F4@1F]U;F1A=&EO;B`H:'1T<#HO+W=W=RYA
M<&%C:&4N;W)G+RDN"@H`````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
7``````````````````````````````H`
`
end

View File

@ -353,12 +353,14 @@ makeextralist(int flags, const char *src)
wchar_t *dst, *d;
size_t len;
const wchar_t *s;
mbstate_t mbstate;
bzero(&mbstate, sizeof(mbstate));
len = strlen(src);
if ((dst = calloc(len + MAXEXTRAS, sizeof(*dst))) == NULL)
return NULL;
if ((flags & VIS_NOLOCALE) || mbstowcs(dst, src, len) == (size_t)-1) {
if ((flags & VIS_NOLOCALE) || mbsrtowcs(dst, &src, len, &mbstate) == (size_t)-1) {
size_t i;
for (i = 0; i < len; i++)
dst[i] = (wchar_t)(u_char)src[i];
@ -400,6 +402,7 @@ istrsenvisx(char **mbdstp, size_t *dlen, const char *mbsrc, size_t mblength,
int clen = 0, cerr, error = -1, i, shft;
char *mbdst, *mdst;
ssize_t mbslength, maxolen;
mbstate_t mbstate;
_DIAGASSERT(mbdstp != NULL);
_DIAGASSERT(mbsrc != NULL || mblength == 0);
@ -456,10 +459,11 @@ istrsenvisx(char **mbdstp, size_t *dlen, const char *mbsrc, size_t mblength,
*/
if (mbslength == 1)
mbslength++;
bzero(&mbstate, sizeof(mbstate));
while (mbslength > 0) {
/* Convert one multibyte character to wchar_t. */
if (!cerr)
clen = mbtowc(src, mbsrc, MB_LEN_MAX);
clen = mbrtowc(src, mbsrc, MB_LEN_MAX, &mbstate);
if (cerr || clen < 0) {
/* Conversion error, process as a byte instead. */
*src = (wint_t)(u_char)*mbsrc;
@ -530,9 +534,10 @@ istrsenvisx(char **mbdstp, size_t *dlen, const char *mbsrc, size_t mblength,
len = wcslen(start);
maxolen = dlen ? *dlen : (wcslen(start) * MB_LEN_MAX + 1);
olen = 0;
bzero(&mbstate, sizeof(mbstate));
for (dst = start; len > 0; len--) {
if (!cerr)
clen = wctomb(mbdst, *dst);
clen = wcrtomb(mbdst, *dst, &mbstate);
if (cerr || clen < 0) {
/*
* Conversion error, process as a byte(s) instead.

View File

@ -1479,8 +1479,27 @@ LazyValueInfo LazyValueAnalysis::run(Function &F, FunctionAnalysisManager &FAM)
return LazyValueInfo(&AC, &TLI, DT);
}
/// Returns true if we can statically tell that this value will never be a
/// "useful" constant. In practice, this means we've got something like an
/// alloca or a malloc call for which a comparison against a constant can
/// only be guarding dead code. Note that we are potentially giving up some
/// precision in dead code (a constant result) in favour of avoiding a
/// expensive search for a easily answered common query.
static bool isKnownNonConstant(Value *V) {
V = V->stripPointerCasts();
// The return val of alloc cannot be a Constant.
if (isa<AllocaInst>(V))
return true;
return false;
}
Constant *LazyValueInfo::getConstant(Value *V, BasicBlock *BB,
Instruction *CxtI) {
// Bail out early if V is known not to be a Constant.
if (isKnownNonConstant(V))
return nullptr;
const DataLayout &DL = BB->getModule()->getDataLayout();
LVILatticeVal Result =
getCache(PImpl, AC, &DL, DT).getValueInBlock(V, BB, CxtI);
@ -1613,6 +1632,17 @@ LazyValueInfo::getPredicateOnEdge(unsigned Pred, Value *V, Constant *C,
LazyValueInfo::Tristate
LazyValueInfo::getPredicateAt(unsigned Pred, Value *V, Constant *C,
Instruction *CxtI) {
// Is or is not NonNull are common predicates being queried. If
// isKnownNonNull can tell us the result of the predicate, we can
// return it quickly. But this is only a fastpath, and falling
// through would still be correct.
if (V->getType()->isPointerTy() && C->isNullValue() &&
isKnownNonNull(V->stripPointerCasts())) {
if (Pred == ICmpInst::ICMP_EQ)
return LazyValueInfo::False;
else if (Pred == ICmpInst::ICMP_NE)
return LazyValueInfo::True;
}
const DataLayout &DL = CxtI->getModule()->getDataLayout();
LVILatticeVal Result = getCache(PImpl, AC, &DL, DT).getValueAt(V, CxtI);
Tristate Ret = getPredicateResult(Pred, C, Result, DL, TLI);

View File

@ -137,16 +137,10 @@ ATF_TC_BODY(mbtowc, tc)
h_mbtowc("ja_JP.ISO2022-JP", "\033$B", "\033$B$\"\033(B");
h_mbtowc("ja_JP.SJIS", "\202", "\202\240");
h_mbtowc("ja_JP.eucJP", "\244", "\244\242");
#ifndef __FreeBSD__
/* Moved last as it fails */
h_mbtowc("zh_CN.GB18030", "\241", "\241\241");
#endif
h_mbtowc("zh_TW.Big5", "\241", "\241@");
h_mbtowc("zh_TW.eucTW", "\241", "\241\241");
#ifdef __FreeBSD__
atf_tc_expect_fail("zh_CN.GB18030");
h_mbtowc("zh_CN.GB18030", "\241", "\241\241");
#endif
}
ATF_TP_ADD_TCS(tp)

View File

@ -1919,7 +1919,7 @@ main(int argc, char **argv)
error("%s", pcap_geterr(pd));
#ifdef HAVE_CASPER
if (RFileName == NULL && VFileName == NULL) {
static const unsigned long cmds[] = { BIOCGSTATS };
static const unsigned long cmds[] = { BIOCGSTATS, BIOCROTZBUF };
/*
* The various libpcap devices use a combination of

View File

@ -1159,7 +1159,7 @@ addarg(char **argv, const char *val)
*/
argv = (char **)malloc(sizeof(*argv) * 12);
if (argv == NULL)
return(NULL);
fatal(net, "failure allocating argument space");
*argv++ = (char *)10;
*argv = (char *)0;
}
@ -1170,11 +1170,12 @@ addarg(char **argv, const char *val)
*argv = (char *)((long)(*argv) + 10);
argv = (char **)realloc(argv, sizeof(*argv)*((long)(*argv) + 2));
if (argv == NULL)
return(NULL);
fatal(net, "failure allocating argument space");
argv++;
cpp = &argv[(long)argv[-1] - 10];
}
*cpp++ = strdup(val);
if ((*cpp++ = strdup(val)) == NULL)
fatal(net, "failure allocating argument space");
*cpp = 0;
return(argv);
}

View File

@ -18,10 +18,10 @@ data should contain commentary citing reliable sources as
justification.
Please submit changes against either the latest release in
<ftp://ftp.iana.org/tz/> or the master branch of the experimental
Git repository. If you use Git the following workflow may be helpful:
<ftp://ftp.iana.org/tz/> or the master branch of the development
repository. If you use Git the following workflow may be helpful:
* Copy the experimental repository.
* Copy the development repository.
git clone https://github.com/eggert/tz.git
cd tz

View File

@ -542,7 +542,8 @@ force_tzs: $(TZS_NEW)
cp $(TZS_NEW) $(TZS)
libtz.a: $(LIBOBJS)
$(AR) ru $@ $(LIBOBJS)
rm -f $@
$(AR) -rc $@ $(LIBOBJS)
$(RANLIB) $@
date: $(DATEOBJS)

View File

@ -1,5 +1,46 @@
News for the tz database
Release 2016j - 2016-11-22 23:17:13 -0800
Briefly: Saratov, Russia moves from +03 to +04 on 2016-12-04.
Changes to future time stamps
Saratov, Russia switches from +03 to +04 on 2016-12-04 at 02:00.
This hives off a new zone Europe/Saratov from Europe/Volgograd.
(Thanks to Yuri Konotopov and Stepan Golosunov.)
Changes to past time stamps
The new zone Asia/Atyrau for Atyraū Region, Kazakhstan, is like
Asia/Aqtau except it switched from +04/+05 to +05/+06 in spring
1999, not fall 1994. (Thanks to Stepan Golosunov.)
Changes to past time zone abbreviations
Asia/Gaza and Asia/Hebron now use "EEST", not "EET", to denote
summer time before 1948. The old use of "EET" was a typo.
Changes to code
zic no longer mishandles file systems that lack hard links, fixing
bugs introduced in 2016g. (Problems reported by Tom Lane.)
Also, when the destination already contains symbolic links, zic
should now work better on systems where the 'link' system call
does not follow symbolic links.
Changes to documentation and commentary
tz-link.htm now documents the relationship between release version
numbers and development-repository commit tags. (Suggested by
Paul Koning.)
The 'Theory' file now documents UT.
iso3166.tab now accents "Curaçao", and commentary now mentions
the names "Cabo Verde" and "Czechia". (Thanks to Jiří Boháč.)
Release 2016i - 2016-11-01 23:19:52 -0700
Briefly: Cyprus split into two time zones on 2016-10-30, and Tonga
@ -212,7 +253,7 @@ Release 2016g - 2016-09-13 08:56:38 -0700
23 commits and some working-file changes have been made since
release 2016g, the version number is now something like
'2016g-23-g50556e3-dirty' instead of the misleading '2016g'.
Official releases uses the same version number format as before,
Tagged releases use the same version number format as before,
e.g., '2016g'. To support the more-accurate version number, its
specification has moved from a line in the Makefile to a new
source file 'version'.

View File

@ -10,24 +10,9 @@ locations around the globe. It is updated periodically to reflect
changes made by political bodies to time zone boundaries, UTC offsets,
and daylight-saving rules.
Here is a recipe for acquiring, building, installing, and testing the
tz distribution on a GNU/Linux or similar host.
To acquire the distribution, run the following shell commands:
mkdir tz
cd tz
wget --retr-symlinks 'ftp://ftp.iana.org/tz/tz*-latest.tar.gz'
gzip -dc tzcode-latest.tar.gz | tar -xf -
gzip -dc tzdata-latest.tar.gz | tar -xf -
Alternatively, the following shell commands acquire the same
distribution, with extra data useful for regression testing:
wget --retr-symlinks 'ftp://ftp.iana.org/tz/tzdb-latest.tar.lz'
lzip -dc tzdb-latest.tar.lz | tar -xf -
Be sure to read the comments in "Makefile" and make any changes needed
See <https://www.iana.org/time-zones/repository/tz-link.html> or the
file tz-link.htm for how to acquire the code and data. Once acquired,
read the comments in the file 'Makefile' and make any changes needed
to make things right for your system, especially if you are using some
platform other than GNU/Linux. Then run the following commands,
substituting your desired installation directory for "$HOME/tzdir":
@ -60,10 +45,6 @@ Thanks in particular to Arthur David Olson, the project's founder and first
maintainer, to whom the time zone community owes the greatest debt of all.
None of them are responsible for remaining errors.
Look in <ftp://ftp.iana.org/tz/releases/> for updated versions of these files.
Please send comments or information to tz@iana.org.
-----
This file is in the public domain, so clarified as of 2009-05-17 by

View File

@ -8,6 +8,7 @@ Theory and pragmatics of the tz code and data
Time zone abbreviations
Accuracy of the tz database
Time and date functions
Interface stability
Calendrical issues
Time and time zones on Mars
@ -342,12 +343,24 @@ Errors in the tz database arise from many sources:
non-hour-based system at night.
* Early clocks were less reliable, and data entries do not represent
this unreliability.
clock error.
* As for leap seconds, civil time was not based on atomic time before
1972, and we don't know the history of earth's rotation accurately
enough to map SI seconds to historical solar time to more than
about one-hour accuracy. See: Morrison LV, Stephenson FR.
* The tz database assumes Universal Time (UT) as an origin, even
though UT is not standardized for older time stamps. In the tz
database commentary, UT denotes a family of time standards that
includes Coordinated Universal Time (UTC) along with other variants
such as UT1 and GMT, with days starting at midnight. Although UT
equals UTC for modern time stamps, UTC was not defined until 1960,
so commentary uses the more-general abbreviation UT for time stamps
that might predate 1960. Since UT, UT1, etc. disagree slightly,
and since pre-1972 UTC seconds varied in length, interpretation of
older time stamps can be problematic when subsecond accuracy is
needed.
* Civil time was not based on atomic time before 1972, and we don't
know the history of earth's rotation accurately enough to map SI
seconds to historical solar time to more than about one-hour
accuracy. See: Morrison LV, Stephenson FR.
Historical values of the Earth's clock error Delta T and the
calculation of eclipses. J Hist Astron. 2004;35:327-36
<http://adsabs.harvard.edu/full/2004JHA....35..327M>;
@ -601,10 +614,14 @@ The tz code and data supply the following interfaces:
* The format of the country code file, documented in iso3166.tab.
When these interfaces are changed, an effort is made to preserve
backward compatibility. For example, tz data files typically do not
rely on recently-added zic features, so that users can run older zic
versions to process newer data files.
* The version number of the code and data, as the first line of
the text file 'version' in each release.
Interface changes in a release attempt to preserve compatibility with
recent releases. For example, tz data files typically do not rely on
recently-added zic features, so that users can run older zic versions
to process newer data files. The tz-link.htm file describes how
releases are tagged and distributed.
Interfaces not listed above are less stable. For example, users
should not rely on particular UT offsets or abbreviations for time

View File

@ -119,7 +119,7 @@ Zone Africa/Algiers 0:12:12 - LMT 1891 Mar 15 0:01
# Cameroon
# See Africa/Lagos.
# Cape Verde
# Cape Verde / Cabo Verde
#
# Shanks gives 1907 for the transition to CVT.
# Perhaps the 1911-05-26 Portuguese decree

View File

@ -1583,12 +1583,12 @@ Zone Asia/Amman 2:23:44 - LMT 1931
# was "blended" with the Central zone. Therefore, Kazakhstan now has
# two time zones, and difference between them is one hour. The zone
# closer to UTC is the former Western zone (probably still called the
# same), encompassing four provinces in the west: Aqtobe, Atyrau,
# Mangghystau, and West Kazakhstan. The other zone encompasses
# same), encompassing four provinces in the west: Aqtöbe, Atyraū,
# Mangghystaū, and West Kazakhstan. The other zone encompasses
# everything else.... I guess that would make Kazakhstan time zones
# de jure UTC+5 and UTC+6 respectively.
# From Stepan Golosunov (2016-03-27) ([*] means see later comments below):
# From Stepan Golosunov (2016-03-27):
# Review of the linked documents from http://adilet.zan.kz/
# produced the following data for post-1991 Kazakhstan:
#
@ -1634,7 +1634,7 @@ Zone Asia/Amman 2:23:44 - LMT 1931
#
# This implies that on 1991-03-31 Asia/Oral remained on +04/+05 while
# the rest of Kazakhstan switched from +06/+07 to +05/06 or from +05/06
# to +04/+05. It's unclear how Kzyl-Orda oblast moved into the fifth
# to +04/+05. It's unclear how Qyzylorda oblast moved into the fifth
# time belt. (By switching from +04/+05 to +05/+06 on 1991-09-29?) ...
#
# 1. Act of the Cabinet of Ministers of the Republic of Kazakhstan
@ -1647,25 +1647,25 @@ Zone Asia/Amman 2:23:44 - LMT 1931
# on the whole territory of Kazakhstan 1 hour forward on 1992-01-19 at
# 2:00, specified DST rules. It acknowledged that Kazakhstan was
# located in the fourth and the fifth time belts and specified the
# border between them to be located east of Kustanay and Aktyubinsk
# oblasts (notably including Turgai and Kzyl-Orda oblasts into the fifth
# border between them to be located east of Qostanay and Aktyubinsk
# oblasts (notably including Turgai and Qyzylorda oblasts into the fifth
# time belt).
#
# This means switch on 1992-01-19 at 2:00 from +04/+05 to +05/+06 for
# Asia/Aqtau, Asia/Aqtobe, Asia/Oral, Atyrau and Kustanay oblasts; from
# +05/+06 to +06/+07 for Asia/Almaty and Asia/Qyzylorda (and Arkalyk) [*]....
# Asia/Aqtau, Asia/Aqtobe, Asia/Oral, Atyraū and Qostanay oblasts; from
# +05/+06 to +06/+07 for Asia/Almaty and Asia/Qyzylorda (and Arkalyk)....
#
# 2. Act of the Cabinet of Ministers of the Republic of Kazakhstan
# from 1992-03-27 No. 284
# http://adilet.zan.kz/rus/docs/P920000284_
# cancels extra hour ("decree time") for Uralsk and Kzyl-Orda oblasts
# cancels extra hour ("decree time") for Uralsk and Qyzylorda oblasts
# since the last Sunday of March 1992, while keeping them in the fourth
# and the fifth time belts respectively.
#
# 3. Order of the Prime Minister of the Republic of Kazakhstan
# from 1994-09-23 No. 384
# http://adilet.zan.kz/rus/docs/R940000384_
# cancels the extra hour ("decree time") on the territory of Mangystau
# cancels the extra hour ("decree time") on the territory of Mangghystaū
# oblast since the last Sunday of September 1994 (saying that time on
# the territory would correspond to the third time belt as a
# result)....
@ -1679,14 +1679,11 @@ Zone Asia/Amman 2:23:44 - LMT 1931
# 5. Act of the Government of the Republic of Kazakhstan
# from 1999-03-26 No. 305
# http://adilet.zan.kz/rus/docs/P990000305_
# cancels the extra hour ("decree time") for Atyrau oblast since the
# cancels the extra hour ("decree time") for Atyraū oblast since the
# last Sunday of March 1999 while retaining the oblast in the fourth
# time belt.
#
# This means change from +05/+06 to +04/+05.
#
# There is no zone for Atyrau currently (listed under Asia/Aqtau in
# zone1970.tab).[*]
# This means change from +05/+06 to +04/+05....
#
# 6. Act of the Government of the Republic of Kazakhstan
# from 2000-11-23 No. 1749
@ -1696,10 +1693,10 @@ Zone Asia/Amman 2:23:44 - LMT 1931
# The only changes I noticed are in definition of the border between the
# fourth and the fifth time belts. They account for changes in spelling
# and administrative division (splitting of Turgai oblast in 1997
# probably changed time in territories incorporated into Kostanay oblast
# (including Arkalyk) from +06/+07 to +05/+06) and move Kyzylorda oblast
# probably changed time in territories incorporated into Qostanay oblast
# (including Arkalyk) from +06/+07 to +05/+06) and move Qyzylorda oblast
# from being in the fifth time belt and not using decree time into the
# fourth time belt (no change in practice).[*]
# fourth time belt (no change in practice).
#
# 7. Act of the Government of the Republic of Kazakhstan
# from 2003-12-29 No. 1342
@ -1709,7 +1706,7 @@ Zone Asia/Amman 2:23:44 - LMT 1931
# 8. Act of the Government of the Republic of Kazakhstan
# from 2004-07-20 No. 775
# http://adilet.zan.kz/rus/archive/docs/P040000775_/20.07.2004
# modified the 2000-11-23 act to move Kostanay and Kyzylorda oblasts into
# modified the 2000-11-23 act to move Qostanay and Qyzylorda oblasts into
# the fifth time belt and add Aktobe oblast to the list of regions not
# using extra hour ("decree time"), leaving Kazakhstan with only 2 time
# zones (+04/+05 and +06/+07). The changes were to be implemented
@ -1721,14 +1718,14 @@ Zone Asia/Amman 2:23:44 - LMT 1931
# http://adilet.zan.kz/rus/docs/P040001059_
# modified the 2000-11-23 act to remove exceptions from the "decree time"
# (leaving Kazakhstan in +05/+06 and +06/+07 zones), amended the
# 2004-07-20 act to implement changes for Atyrau, West Kazakhstan,
# Kostanay, Kyzylorda and Mangystau oblasts by not moving clocks
# during the 2014 transition to "winter" time.
# 2004-07-20 act to implement changes for Atyraū, West Kazakhstan,
# Qostanay, Qyzylorda and Mangghystaū oblasts by not moving clocks
# during the 2004 transition to "winter" time.
#
# This means transition from +04/+05 to +05/+06 for Atyrau oblast (no
# This means transition from +04/+05 to +05/+06 for Atyraū oblast (no
# zone currently), Asia/Oral, Asia/Aqtau and transition from +05/+06 to
# +06/+07 for Kostanay oblast (Kostanay and Arkalyk, no zones currently)
# and Asia/Qyzylorda on 2004-10-31 at 3:00....[*]
# +06/+07 for Qostanay oblast (Qostanay and Arkalyk, no zones currently)
# and Asia/Qyzylorda on 2004-10-31 at 3:00....
#
# 10. Act of the Government of the Republic of Kazakhstan
# from 2005-03-15 No. 231
@ -1744,14 +1741,9 @@ Zone Asia/Amman 2:23:44 - LMT 1931
# Kazakh 1992-01-13 act appears to provide the same rules and 1992-03-27
# act was to be enacted on the last Sunday of March 1992.
# From Paul Eggert (2016-04-15):
# The tables below should reflect Stepan Golosunov's remarks above,
# except for the items marked "[*]" which I haven't gotten to yet.
# It looks like we will need new zones Asia/Atyrau and Asia/Qostanay
# to handle changes from 1992 through 2004 that we did not previously
# know about.
# From Paul Eggert (2016-11-07):
# The tables below reflect Golosunov's remarks, with exceptions as noted.
#
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
#
# Almaty (formerly Alma-Ata), representing most locations in Kazakhstan
@ -1764,6 +1756,8 @@ Zone Asia/Almaty 5:07:48 - LMT 1924 May 2 # or Alma-Ata
6:00 RussiaAsia +06/+07 2004 Oct 31 2:00s
6:00 - +06
# Qyzylorda (aka Kyzylorda, Kizilorda, Kzyl-Orda, etc.) (KZ-KZY)
# This currently includes Qostanay (aka Kostanay, Kustanay) (KZ-KUS);
# see comments below.
Zone Asia/Qyzylorda 4:21:52 - LMT 1924 May 2
4:00 - +04 1930 Jun 21
5:00 - +05 1981 Apr 1
@ -1775,7 +1769,21 @@ Zone Asia/Qyzylorda 4:21:52 - LMT 1924 May 2
6:00 RussiaAsia +06/+07 1992 Mar 29 2:00s
5:00 RussiaAsia +05/+06 2004 Oct 31 2:00s
6:00 - +06
# Aqtobe (aka Aktobe, formerly Aktyubinsk) (KZ-AKT)
# The following zone is like Asia/Qyzylorda except for being one
# hour earlier from 1991-09-29 to 1992-03-29. The 1991/2 rules for
# Qostenay are unclear partly because of the 1997 Turgai
# reorganization, so this zone is commented out for now.
#Zone Asia/Qostanay 4:14:20 - LMT 1924 May 2
# 4:00 - +04 1930 Jun 21
# 5:00 - +05 1981 Apr 1
# 5:00 1:00 +06 1981 Oct 1
# 6:00 - +06 1982 Apr 1
# 5:00 RussiaAsia +05/+06 1991 Mar 31 2:00s
# 4:00 RussiaAsia +04/+05 1992 Jan 19 2:00s
# 5:00 RussiaAsia +05/+06 2004 Oct 31 2:00s
# 6:00 - +06
#
# Aqtöbe (aka Aktobe, formerly Aktyubinsk) (KZ-AKT)
Zone Asia/Aqtobe 3:48:40 - LMT 1924 May 2
4:00 - +04 1930 Jun 21
5:00 - +05 1981 Apr 1
@ -1785,14 +1793,11 @@ Zone Asia/Aqtobe 3:48:40 - LMT 1924 May 2
4:00 RussiaAsia +04/+05 1992 Jan 19 2:00s
5:00 RussiaAsia +05/+06 2004 Oct 31 2:00s
5:00 - +05
# Qostanay (KZ-KUS)
# Mangghystau (KZ-MAN)
# Mangghystaū (KZ-MAN)
# Aqtau was not founded until 1963, but it represents an inhabited region,
# so include time stamps before 1963.
Zone Asia/Aqtau 3:21:04 - LMT 1924 May 2
4:00 - +04 1930 Jun 21
5:00 - +05 1963
5:00 - +05 1981 Oct 1
6:00 - +06 1982 Apr 1
5:00 RussiaAsia +05/+06 1991 Mar 31 2:00s
@ -1800,7 +1805,17 @@ Zone Asia/Aqtau 3:21:04 - LMT 1924 May 2
5:00 RussiaAsia +05/+06 1994 Sep 25 2:00s
4:00 RussiaAsia +04/+05 2004 Oct 31 2:00s
5:00 - +05
# Atyraū (KZ-ATY) is like Mangghystaū except it switched from
# +04/+05 to +05/+06 in spring 1999, not fall 1994.
Zone Asia/Atyrau 3:27:44 - LMT 1924 May 2
4:00 - +04 1930 Jun 21
5:00 - +05 1981 Oct 1
6:00 - +06 1982 Apr 1
5:00 RussiaAsia +05/+06 1991 Mar 31 2:00s
4:00 RussiaAsia +04/+05 1992 Jan 19 2:00s
5:00 RussiaAsia +05/+06 1999 Mar 28 2:00s
4:00 RussiaAsia +04/+05 2004 Oct 31 2:00s
5:00 - +05
# West Kazakhstan (KZ-ZAP)
# From Paul Eggert (2016-03-18):
# The 1989 transition is from USSR act No. 227 (1989-03-14).
@ -2616,7 +2631,7 @@ Rule Palestine 2016 max - Oct lastSat 1:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Gaza 2:17:52 - LMT 1900 Oct
2:00 Zion EET 1948 May 15
2:00 Zion EET/EEST 1948 May 15
2:00 EgyptAsia EE%sT 1967 Jun 5
2:00 Zion I%sT 1996
2:00 Jordan EE%sT 1999
@ -2629,7 +2644,7 @@ Zone Asia/Gaza 2:17:52 - LMT 1900 Oct
2:00 Palestine EE%sT
Zone Asia/Hebron 2:20:23 - LMT 1900 Oct
2:00 Zion EET 1948 May 15
2:00 Zion EET/EEST 1948 May 15
2:00 EgyptAsia EE%sT 1967 Jun 5
2:00 Zion I%sT 1996
2:00 Jordan EE%sT 1999

View File

@ -901,7 +901,7 @@ Zone Europe/Sofia 1:33:16 - LMT 1880
# Cyprus
# Please see the 'asia' file for Asia/Nicosia.
# Czech Republic
# Czech Republic / Czechia
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Czech 1945 only - Apr 8 2:00s 1:00 S
Rule Czech 1945 only - Nov 18 2:00s 0 -
@ -2601,10 +2601,9 @@ Zone Europe/Astrakhan 3:12:12 - LMT 1924 May
3:00 - +03 2016 Mar 27 2:00s
4:00 - +04
# From Paul Eggert (2016-03-18):
# From Paul Eggert (2016-11-11):
# Europe/Volgograd covers:
# 34 RU-VGG Volgograd Oblast
# 64 RU-SAR Saratov Oblast
# The 1988 transition is from USSR act No. 5 (1988-01-04).
Zone Europe/Volgograd 2:57:40 - LMT 1920 Jan 3
@ -2617,6 +2616,27 @@ Zone Europe/Volgograd 2:57:40 - LMT 1920 Jan 3
4:00 - +04 2014 Oct 26 2:00s
3:00 - +03
# From Paul Eggert (2016-11-11):
# Europe/Saratov covers:
# 64 RU-SAR Saratov Oblast
# From Yuri Konotopov (2016-11-11):
# Dec 4, 2016 02:00 UTC+3.... Saratov Region's local time will be ... UTC+4.
# From Stepan Golosunov (2016-11-11):
# ... Byalokoz listed Saratov on 03:04:18.
# From Stepan Golosunov (2016-11-22):
# http://publication.pravo.gov.ru/Document/View/0001201611220031
Zone Europe/Saratov 3:04:18 - LMT 1919 Jul 1 0:00u
3:00 - +03 1930 Jun 21
4:00 Russia +04/+05 1988 Mar 27 2:00s
3:00 Russia +03/+04 1991 Mar 31 2:00s
4:00 - +04 1992 Mar 29 2:00s
3:00 Russia +03/+04 2011 Mar 27 2:00s
4:00 - +04 2014 Oct 26 2:00s
3:00 - +03 2016 Dec 4 2:00s
4:00 - +04
# From Paul Eggert (2016-03-18):
# Europe/Kirov covers:
# 43 RU-KIR Kirov Oblast

View File

@ -1 +1 @@
2016i
2016j

View File

@ -239,7 +239,8 @@ KY +1918-08123 America/Cayman
KZ +4315+07657 Asia/Almaty Kazakhstan (most areas)
KZ +4448+06528 Asia/Qyzylorda Qyzylorda/Kyzylorda/Kzyl-Orda
KZ +5017+05710 Asia/Aqtobe Aqtobe/Aktobe
KZ +4431+05016 Asia/Aqtau Atyrau/Atirau/Gur'yev, Mangghystau/Mankistau
KZ +4431+05016 Asia/Aqtau Mangghystau/Mankistau
KZ +4707+05156 Asia/Atyrau Atyrau/Atirau/Gur'yev
KZ +5113+05121 Asia/Oral West Kazakhstan
LA +1758+10236 Asia/Vientiane
LB +3353+03530 Asia/Beirut
@ -330,14 +331,15 @@ RS +4450+02030 Europe/Belgrade
RU +5443+02030 Europe/Kaliningrad MSK-01 - Kaliningrad
RU +554521+0373704 Europe/Moscow MSK+00 - Moscow area
RU +4457+03406 Europe/Simferopol MSK+00 - Crimea
RU +4844+04425 Europe/Volgograd MSK+00 - Volgograd, Saratov
RU +4844+04425 Europe/Volgograd MSK+00 - Volgograd
RU +5836+04939 Europe/Kirov MSK+00 - Kirov
RU +4621+04803 Europe/Astrakhan MSK+01 - Astrakhan
RU +5312+05009 Europe/Samara MSK+01 - Samara, Udmurtia
RU +5134+04602 Europe/Saratov MSK+01 - Saratov
RU +5420+04824 Europe/Ulyanovsk MSK+01 - Ulyanovsk
RU +5312+05009 Europe/Samara MSK+01 - Samara, Udmurtia
RU +5651+06036 Asia/Yekaterinburg MSK+02 - Urals
RU +5500+07324 Asia/Omsk MSK+03 - Omsk
RU +5502+08255 Asia/Novosibirsk MSK+03 - Novosibirsk
RU +5502+08255 Asia/Novosibirsk MSK+04 - Novosibirsk
RU +5322+08345 Asia/Barnaul MSK+04 - Altai
RU +5630+08458 Asia/Tomsk MSK+04 - Tomsk
RU +5345+08707 Asia/Novokuznetsk MSK+04 - Kemerovo

View File

@ -211,8 +211,9 @@ KP +3901+12545 Asia/Pyongyang
KR +3733+12658 Asia/Seoul
KZ +4315+07657 Asia/Almaty Kazakhstan (most areas)
KZ +4448+06528 Asia/Qyzylorda Qyzylorda/Kyzylorda/Kzyl-Orda
KZ +5017+05710 Asia/Aqtobe Aqtobe/Aktobe
KZ +4431+05016 Asia/Aqtau Atyrau/Atirau/Gur'yev, Mangghystau/Mankistau
KZ +5017+05710 Asia/Aqtobe Aqtöbe/Aktobe
KZ +4431+05016 Asia/Aqtau Mangghystaū/Mankistau
KZ +4707+05156 Asia/Atyrau Atyraū/Atirau/Gur'yev
KZ +5113+05121 Asia/Oral West Kazakhstan
LB +3353+03530 Asia/Beirut
LK +0656+07951 Asia/Colombo
@ -288,14 +289,15 @@ RS,BA,HR,ME,MK,SI +4450+02030 Europe/Belgrade
RU +5443+02030 Europe/Kaliningrad MSK-01 - Kaliningrad
RU +554521+0373704 Europe/Moscow MSK+00 - Moscow area
RU +4457+03406 Europe/Simferopol MSK+00 - Crimea
RU +4844+04425 Europe/Volgograd MSK+00 - Volgograd, Saratov
RU +4844+04425 Europe/Volgograd MSK+00 - Volgograd
RU +5836+04939 Europe/Kirov MSK+00 - Kirov
RU +4621+04803 Europe/Astrakhan MSK+01 - Astrakhan
RU +5312+05009 Europe/Samara MSK+01 - Samara, Udmurtia
RU +5134+04602 Europe/Saratov MSK+01 - Saratov
RU +5420+04824 Europe/Ulyanovsk MSK+01 - Ulyanovsk
RU +5312+05009 Europe/Samara MSK+01 - Samara, Udmurtia
RU +5651+06036 Asia/Yekaterinburg MSK+02 - Urals
RU +5500+07324 Asia/Omsk MSK+03 - Omsk
RU +5502+08255 Asia/Novosibirsk MSK+03 - Novosibirsk
RU +5502+08255 Asia/Novosibirsk MSK+04 - Novosibirsk
RU +5322+08345 Asia/Barnaul MSK+04 - Altai
RU +5630+08458 Asia/Tomsk MSK+04 - Tomsk
RU +5345+08707 Asia/Novokuznetsk MSK+04 - Kemerovo

View File

@ -120,6 +120,9 @@ pccard_ether_restart()
pccard_ether_startchildren()
{
for child in `get_if_var $ifn wlans_IF`; do
if ifexists $child; then
continue
fi
/etc/rc.d/netif quietstart $child
done
}

View File

@ -7,6 +7,9 @@ INTERNALLIB=
SRCDIR= lib
SRCS+= Support/APInt.cpp
.if ${MACHINE_ARCH:Mpowerpc*} != ""
SRCS+= Support/Atomic.cpp
.endif
SRCS+= Support/CommandLine.cpp
SRCS+= Support/ConvertUTF.c
SRCS+= Support/ConvertUTFWrapper.cpp

View File

@ -72,6 +72,7 @@ TESTS_SRCS= \
test_compat_mac.c \
test_compat_pax_libarchive_2x.c \
test_compat_perl_archive_tar.c \
test_compat_plexus_archiver_tar.c \
test_compat_solaris_tar_acl.c \
test_compat_solaris_pax_sparse.c \
test_compat_star_acl_posix1e.c \
@ -350,6 +351,7 @@ ${PACKAGE}FILES+= test_compat_mac-1.tar.Z.uu
${PACKAGE}FILES+= test_compat_mac-2.tar.Z.uu
${PACKAGE}FILES+= test_compat_pax_libarchive_2x.tar.Z.uu
${PACKAGE}FILES+= test_compat_perl_archive_tar.tar.uu
${PACKAGE}FILES+= test_compat_plexus_archiver_tar.tar.uu
${PACKAGE}FILES+= test_compat_solaris_pax_sparse_1.pax.Z.uu
${PACKAGE}FILES+= test_compat_solaris_pax_sparse_2.pax.Z.uu
${PACKAGE}FILES+= test_compat_solaris_tar_acl.tar.uu

View File

@ -14,11 +14,14 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <stdint.h>
#include "rand48.h"
long
jrand48(unsigned short xseed[3])
{
_dorand48(xseed);
return ((long) xseed[2] << 16) + (long) xseed[1];
return ((int32_t)(((uint32_t)xseed[2] << 16) | (uint32_t)xseed[1]));
}

View File

@ -14,6 +14,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <stdint.h>
#include "rand48.h"
extern unsigned short _rand48_seed[3];
@ -21,6 +23,8 @@ extern unsigned short _rand48_seed[3];
long
mrand48(void)
{
_dorand48(_rand48_seed);
return ((long) _rand48_seed[2] << 16) + (long) _rand48_seed[1];
return ((int32_t)(((uint32_t)_rand48_seed[2] << 16) |
(uint32_t)_rand48_seed[1]));
}

View File

@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <string.h>
@ -122,31 +123,46 @@ char *
link_ntoa(const struct sockaddr_dl *sdl)
{
static char obuf[64];
char *out = obuf;
int i;
u_char *in = (u_char *)LLADDR(sdl);
u_char *inlim = in + sdl->sdl_alen;
int firsttime = 1;
_Static_assert(sizeof(obuf) >= IFNAMSIZ + 20, "obuf is too small");
char *out;
const u_char *in, *inlim;
int namelen, i, rem;
if (sdl->sdl_nlen) {
bcopy(sdl->sdl_data, obuf, sdl->sdl_nlen);
out += sdl->sdl_nlen;
if (sdl->sdl_alen)
namelen = (sdl->sdl_nlen <= IFNAMSIZ) ? sdl->sdl_nlen : IFNAMSIZ;
out = obuf;
rem = sizeof(obuf);
if (namelen > 0) {
bcopy(sdl->sdl_data, out, namelen);
out += namelen;
rem -= namelen;
if (sdl->sdl_alen > 0) {
*out++ = ':';
rem--;
}
while (in < inlim) {
if (firsttime)
firsttime = 0;
else
}
in = (const u_char *)sdl->sdl_data + sdl->sdl_nlen;
inlim = in + sdl->sdl_alen;
while (in < inlim && rem > 1) {
if (in != (const u_char *)sdl->sdl_data + sdl->sdl_nlen) {
*out++ = '.';
rem--;
}
i = *in++;
if (i > 0xf) {
out[1] = hexlist[i & 0xf];
i >>= 4;
out[0] = hexlist[i];
out += 2;
} else
if (rem < 3)
break;
*out++ = hexlist[i >> 4];
*out++ = hexlist[i & 0xf];
rem -= 2;
} else {
if (rem < 2)
break;
*out++ = hexlist[i];
rem--;
}
}
*out = 0;
return (obuf);

View File

@ -797,7 +797,7 @@ sctp_sendmsgx(int sd,
memset((void *)&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
sinfo.sinfo_ppid = ppid;
sinfo.sinfo_flags = flags;
sinfo.sinfo_ssn = stream_no;
sinfo.sinfo_stream = stream_no;
sinfo.sinfo_timetolive = timetolive;
sinfo.sinfo_context = context;
return (sctp_sendx(sd, msg, len, addrs, addrcnt, &sinfo, 0));

View File

@ -176,7 +176,7 @@ sdump_group(struct group *grp, char *buffer, size_t buflen)
char **cp;
int written;
written = snprintf(buffer, buflen, "%s %s %d",
written = snprintf(buffer, buflen, "%s:%s:%d:",
grp->gr_name, grp->gr_passwd, grp->gr_gid);
buffer += written;
if (written > buflen)
@ -186,7 +186,8 @@ sdump_group(struct group *grp, char *buffer, size_t buflen)
if (grp->gr_mem != NULL) {
if (*(grp->gr_mem) != '\0') {
for (cp = grp->gr_mem; *cp; ++cp) {
written = snprintf(buffer, buflen, " %s",*cp);
written = snprintf(buffer, buflen, "%s%s",
cp == grp->gr_mem ? "" : ",", *cp);
buffer += written;
if (written > buflen)
return;
@ -206,6 +207,7 @@ group_read_snapshot_func(struct group *grp, char *line)
{
StringList *sl;
char *s, *ps, *ts;
const char *sep;
int i;
printf("1 line read from snapshot:\n%s\n", line);
@ -213,8 +215,9 @@ group_read_snapshot_func(struct group *grp, char *line)
i = 0;
sl = NULL;
ps = line;
sep = ":";
memset(grp, 0, sizeof(struct group));
while ((s = strsep(&ps, " ")) != NULL) {
while ((s = strsep(&ps, sep)) != NULL) {
switch (i) {
case 0:
grp->gr_name = strdup(s);
@ -235,6 +238,8 @@ group_read_snapshot_func(struct group *grp, char *line)
grp->gr_passwd = NULL;
return (-1);
}
/* Change to parsing groups. */
sep = ",";
break;
default:

View File

@ -335,7 +335,6 @@ fetch_connect(const char *host, int port, int af, int verbose)
fetch_info("resolving server address: %s:%d", host, port);
if ((sais = fetch_resolve(host, port, af)) == NULL)
goto fail;
fetch_info("resolved");
/* resolve client address */
bindaddr = getenv("FETCH_BIND_ADDRESS");

View File

@ -426,8 +426,6 @@ nopgrp:
kp->ki_pri.pri_native = mtd.td_base_pri;
kp->ki_lastcpu = mtd.td_lastcpu;
kp->ki_wchan = mtd.td_wchan;
if (mtd.td_name[0] != 0)
strlcpy(kp->ki_tdname, mtd.td_name, MAXCOMLEN);
kp->ki_oncpu = mtd.td_oncpu;
if (mtd.td_name[0] != '\0')
strlcpy(kp->ki_tdname, mtd.td_name, sizeof(kp->ki_tdname));

View File

@ -5,7 +5,8 @@
PACKAGE=lib${LIB}
LIB= proc
SRCS= proc_bkpt.c \
SRCS= crc32.c \
proc_bkpt.c \
proc_create.c \
proc_regs.c \
proc_sym.c \
@ -36,7 +37,7 @@ CFLAGS+= -I${.CURDIR}/../../cddl/contrib/opensolaris/lib/libctf/common \
CFLAGS+= -DNO_CTF
.endif
SHLIB_MAJOR= 3
SHLIB_MAJOR= 4
MAN=

View File

@ -26,29 +26,56 @@
* $FreeBSD$
*/
#ifndef __LIBPROC_H_
#define __LIBPROC_H_
#include <sys/types.h>
#include <sys/ptrace.h>
#include <libelf.h>
#include <rtld_db.h>
#include "libproc.h"
struct procstat;
struct symtab {
Elf_Data *data;
u_int nsyms;
u_int *index;
u_long stridx;
};
struct file_info {
Elf *elf;
int fd;
u_int refs;
GElf_Ehdr ehdr;
/* Symbol tables, sorted by value. */
struct symtab dynsymtab;
struct symtab symtab;
};
struct map_info {
prmap_t map;
struct file_info *file;
};
struct proc_handle {
pid_t pid; /* Process ID. */
struct proc_handle_public public; /* Public fields. */
int flags; /* Process flags. */
int status; /* Process status (PS_*). */
int wstat; /* Process wait status. */
int model; /* Process data model. */
rd_agent_t *rdap; /* librtld_db agent */
rd_loadobj_t *rdobjs; /* Array of loaded objects. */
size_t rdobjsz; /* Array size. */
size_t nobjs; /* Num. objects currently loaded. */
rd_loadobj_t *rdexec; /* rdobj for program executable. */
struct lwpstatus lwps; /* Process status. */
struct map_info *mappings; /* File mappings for proc. */
size_t maparrsz; /* Map array size. */
size_t nmappings; /* Number of mappings. */
prmap_t *exec_map; /* Executable text mapping. */
lwpstatus_t lwps; /* Process status. */
struct procstat *procstat; /* libprocstat handle. */
char execpath[MAXPATHLEN]; /* Path to program executable. */
char execpath[PATH_MAX]; /* Path to program executable. */
};
#ifdef DEBUG
@ -58,3 +85,5 @@ struct proc_handle {
#define DPRINTF(...) do { } while (0)
#define DPRINTFX(...) do { } while (0)
#endif
#endif /* __LIBPROC_H_ */

57
lib/libproc/crc32.c Normal file
View File

@ -0,0 +1,57 @@
/*-
* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
* code or tables extracted from it, as desired without restriction.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <stdint.h>
#include <crc32.h>
uint32_t crc32_tab[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};

28
lib/libproc/crc32.h Normal file
View File

@ -0,0 +1,28 @@
/*-
* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
* code or tables extracted from it, as desired without restriction.
*
* $FreeBSD$
*/
#ifndef _CRC32_H_
#define _CRC32_H_
#include <stdint.h> /* uint32_t */
#include <stdlib.h> /* size_t */
extern uint32_t crc32_tab[];
static __inline uint32_t
crc32(const void *buf, size_t size)
{
const uint8_t *p = buf;
uint32_t crc;
crc = ~0U;
while (size--)
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
return (crc ^ ~0U);
}
#endif /* !_CRC32_H_ */

View File

@ -50,6 +50,11 @@ typedef void (*proc_child_func)(void *);
#define PS_DEAD 5
#define PS_LOST 6
/* Flags for proc_attach(). */
#define PATTACH_FORCE 0x01
#define PATTACH_RDONLY 0x02
#define PATTACH_NOSTOP 0x04
/* Reason values for proc_detach(). */
#define PRELEASE_HANG 1
#define PRELEASE_KILL 2
@ -116,13 +121,18 @@ typedef struct lwpstatus {
#define PR_MODEL_ILP32 1
#define PR_MODEL_LP64 2
struct proc_handle_public {
pid_t pid;
};
#define proc_getpid(phdl) (((struct proc_handle_public *)(phdl))->pid)
/* Function prototype definitions. */
__BEGIN_DECLS
prmap_t *proc_addr2map(struct proc_handle *, uintptr_t);
prmap_t *proc_name2map(struct proc_handle *, const char *);
char *proc_objname(struct proc_handle *, uintptr_t, char *, size_t);
prmap_t *proc_obj2map(struct proc_handle *, const char *);
int proc_iter_objs(struct proc_handle *, proc_map_f *, void *);
int proc_iter_symbyaddr(struct proc_handle *, const char *, int,
int, proc_sym_f *, void *);
@ -140,7 +150,6 @@ struct ctf_file *proc_name2ctf(struct proc_handle *, const char *);
int proc_setflags(struct proc_handle *, int);
int proc_state(struct proc_handle *);
int proc_getmodel(struct proc_handle *);
pid_t proc_getpid(struct proc_handle *);
int proc_wstatus(struct proc_handle *);
int proc_getwstat(struct proc_handle *);
char * proc_signame(int, char *, size_t);
@ -158,4 +167,4 @@ int proc_regset(struct proc_handle *, proc_reg_t, unsigned long);
__END_DECLS
#endif /* !_LIBPROC_H_ */
#endif /* _LIBPROC_H_ */

View File

@ -1,4 +1,4 @@
/*
/*-
* Copyright (c) 2010 The FreeBSD Foundation
* All rights reserved.
*
@ -33,13 +33,13 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <machine/_inttypes.h>
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include "_libproc.h"
#if defined(__aarch64__)
@ -130,8 +130,8 @@ proc_bkptset(struct proc_handle *phdl, uintptr_t address,
piod.piod_addr = &instr;
piod.piod_len = BREAKPOINT_INSTR_SZ;
if (ptrace(PT_IO, proc_getpid(phdl), (caddr_t)&piod, 0) < 0) {
DPRINTF("ERROR: couldn't read instruction at address 0x%"
PRIuPTR, address);
DPRINTF("ERROR: couldn't read instruction at address 0x%jx",
(uintmax_t)address);
ret = -1;
goto done;
}
@ -146,8 +146,8 @@ proc_bkptset(struct proc_handle *phdl, uintptr_t address,
piod.piod_addr = &instr;
piod.piod_len = BREAKPOINT_INSTR_SZ;
if (ptrace(PT_IO, proc_getpid(phdl), (caddr_t)&piod, 0) < 0) {
DPRINTF("ERROR: couldn't write instruction at address 0x%"
PRIuPTR, address);
DPRINTF("ERROR: couldn't write instruction at address 0x%jx",
(uintmax_t)address);
ret = -1;
goto done;
}
@ -194,8 +194,8 @@ proc_bkptdel(struct proc_handle *phdl, uintptr_t address,
piod.piod_addr = &instr;
piod.piod_len = BREAKPOINT_INSTR_SZ;
if (ptrace(PT_IO, proc_getpid(phdl), (caddr_t)&piod, 0) < 0) {
DPRINTF("ERROR: couldn't write instruction at address 0x%"
PRIuPTR, address);
DPRINTF("ERROR: couldn't write instruction at address 0x%jx",
(uintmax_t)address);
ret = -1;
}

View File

@ -22,10 +22,11 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/user.h>
@ -78,7 +79,7 @@ proc_init(pid_t pid, int flags, int status, struct proc_handle **pphdl)
goto out;
memset(phdl, 0, sizeof(*phdl));
phdl->pid = pid;
phdl->public.pid = pid;
phdl->flags = flags;
phdl->status = status;
phdl->procstat = procstat_open_sysctl();
@ -126,7 +127,7 @@ proc_attach(pid_t pid, int flags, struct proc_handle **pphdl)
struct proc_handle *phdl;
int error, status;
if (pid == 0 || pid == getpid())
if (pid == 0 || (pid == getpid() && (flags & PATTACH_RDONLY) == 0))
return (EINVAL);
if (elf_version(EV_CURRENT) == EV_NONE)
return (ENOENT);
@ -139,7 +140,8 @@ proc_attach(pid_t pid, int flags, struct proc_handle **pphdl)
if (error != 0)
goto out;
if (ptrace(PT_ATTACH, phdl->pid, 0, 0) != 0) {
if ((flags & PATTACH_RDONLY) == 0) {
if (ptrace(PT_ATTACH, proc_getpid(phdl), 0, 0) != 0) {
error = errno;
DPRINTF("ERROR: cannot ptrace child process %d", pid);
goto out;
@ -158,8 +160,12 @@ proc_attach(pid_t pid, int flags, struct proc_handle **pphdl)
else
phdl->status = PS_STOP;
if ((flags & PATTACH_NOSTOP) != 0)
proc_continue(phdl);
}
out:
if (error && phdl != NULL) {
if (error != 0 && phdl != NULL) {
proc_free(phdl);
phdl = NULL;
}
@ -229,8 +235,28 @@ bad:
void
proc_free(struct proc_handle *phdl)
{
struct file_info *file;
size_t i;
for (i = 0; i < phdl->nmappings; i++) {
file = phdl->mappings[i].file;
if (file != NULL && --file->refs == 0) {
if (file->elf != NULL) {
(void)elf_end(file->elf);
(void)close(file->fd);
if (file->symtab.nsyms > 0)
free(file->symtab.index);
if (file->dynsymtab.nsyms > 0)
free(file->dynsymtab.index);
}
free(file);
}
}
if (phdl->maparrsz > 0)
free(phdl->mappings);
if (phdl->procstat != NULL)
procstat_close(phdl->procstat);
if (phdl->rdap != NULL)
rd_delete(phdl->rdap);
free(phdl);
}

View File

@ -1,4 +1,4 @@
/*
/*-
* Copyright (c) 2010 The FreeBSD Foundation
* All rights reserved.
*
@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "_libproc.h"
int

View File

@ -1,4 +1,4 @@
/*
/*-
* Copyright (c) 2010 The FreeBSD Foundation
* All rights reserved.
*
@ -31,46 +31,99 @@
__FBSDID("$FreeBSD$");
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
#include <rtld_db.h>
#include "libproc.h"
#include "_libproc.h"
static void rdl2prmap(const rd_loadobj_t *, prmap_t *);
static int
map_iter(const rd_loadobj_t *lop, void *arg)
{
struct proc_handle *phdl = arg;
struct file_info *file;
struct map_info *mapping, *tmp;
struct proc_handle *phdl;
size_t i;
if (phdl->nobjs >= phdl->rdobjsz) {
phdl->rdobjsz *= 2;
phdl->rdobjs = reallocf(phdl->rdobjs, sizeof(*phdl->rdobjs) *
phdl->rdobjsz);
if (phdl->rdobjs == NULL)
phdl = arg;
if (phdl->nmappings >= phdl->maparrsz) {
phdl->maparrsz *= 2;
tmp = reallocarray(phdl->mappings, phdl->maparrsz,
sizeof(*phdl->mappings));
if (tmp == NULL)
return (-1);
phdl->mappings = tmp;
}
mapping = &phdl->mappings[phdl->nmappings];
rdl2prmap(lop, &mapping->map);
if (strcmp(lop->rdl_path, phdl->execpath) == 0 &&
(lop->rdl_prot & RD_RDL_X) != 0)
phdl->rdexec = &phdl->rdobjs[phdl->nobjs];
memcpy(&phdl->rdobjs[phdl->nobjs++], lop, sizeof(*lop));
phdl->exec_map = &mapping->map;
file = NULL;
if (lop->rdl_path[0] != '\0') {
/* Look for an existing mapping of the same file. */
for (i = 0; i < phdl->nmappings; i++)
if (strcmp(mapping->map.pr_mapname,
phdl->mappings[i].map.pr_mapname) == 0) {
file = phdl->mappings[i].file;
break;
}
if (file == NULL) {
file = malloc(sizeof(*file));
if (file == NULL)
return (-1);
file->elf = NULL;
file->fd = -1;
file->refs = 1;
} else
file->refs++;
}
mapping->file = file;
phdl->nmappings++;
return (0);
}
static void
rdl2prmap(const rd_loadobj_t *rdl, prmap_t *map)
{
map->pr_vaddr = rdl->rdl_saddr;
map->pr_size = rdl->rdl_eaddr - rdl->rdl_saddr;
map->pr_offset = rdl->rdl_offset;
map->pr_mflags = 0;
if (rdl->rdl_prot & RD_RDL_R)
map->pr_mflags |= MA_READ;
if (rdl->rdl_prot & RD_RDL_W)
map->pr_mflags |= MA_WRITE;
if (rdl->rdl_prot & RD_RDL_X)
map->pr_mflags |= MA_EXEC;
(void)strlcpy(map->pr_mapname, rdl->rdl_path,
sizeof(map->pr_mapname));
}
rd_agent_t *
proc_rdagent(struct proc_handle *phdl)
{
if (phdl->rdap == NULL && phdl->status != PS_UNDEAD &&
phdl->status != PS_IDLE) {
if ((phdl->rdap = rd_new(phdl)) != NULL) {
phdl->rdobjs = malloc(sizeof(*phdl->rdobjs) * 64);
phdl->rdobjsz = 64;
if (phdl->rdobjs == NULL)
return (phdl->rdap);
rd_loadobj_iter(phdl->rdap, map_iter, phdl);
}
}
if ((phdl->rdap = rd_new(phdl)) == NULL)
return (NULL);
phdl->maparrsz = 64;
phdl->mappings = calloc(phdl->maparrsz,
sizeof(*phdl->mappings));
if (phdl->mappings == NULL)
return (phdl->rdap);
if (rd_loadobj_iter(phdl->rdap, map_iter, phdl) != RD_OK)
return (NULL);
}
return (phdl->rdap);
}
@ -78,7 +131,6 @@ void
proc_updatesyms(struct proc_handle *phdl)
{
memset(phdl->rdobjs, 0, sizeof(*phdl->rdobjs) * phdl->rdobjsz);
phdl->nobjs = 0;
memset(phdl->mappings, 0, sizeof(*phdl->mappings) * phdl->maparrsz);
rd_loadobj_iter(phdl->rdap, map_iter, phdl);
}

View File

@ -1,4 +1,5 @@
/*-
* Copyright (c) 2016 Mark Johnston <markj@FreeBSD.org>
* Copyright (c) 2010 The FreeBSD Foundation
* Copyright (c) 2008 John Birrell (jb@freebsd.org)
* All rights reserved.
@ -51,8 +52,11 @@ __FBSDID("$FreeBSD$");
#endif
#include <libutil.h>
#include "crc32.h"
#include "_libproc.h"
#define PATH_DEBUG_DIR "/usr/lib/debug"
#ifdef NO_CTF
typedef struct ctf_file ctf_file_t;
#endif
@ -61,7 +65,21 @@ typedef struct ctf_file ctf_file_t;
extern char *__cxa_demangle(const char *, char *, size_t *, int *);
#endif /* NO_CXA_DEMANGLE */
static void proc_rdl2prmap(rd_loadobj_t *, prmap_t *);
static int
crc32_file(int fd, uint32_t *crc)
{
uint8_t buf[PAGE_SIZE], *p;
size_t n;
*crc = ~0;
while ((n = read(fd, buf, sizeof(buf))) > 0) {
p = &buf[0];
while (n-- > 0)
*crc = crc32_tab[(*crc ^ *p++) & 0xff] ^ (*crc >> 8);
}
*crc = ~*crc;
return (n);
}
static void
demangle(const char *symbol, char *buf, size_t len)
@ -83,341 +101,427 @@ fail:
}
static int
find_dbg_obj(const char *path)
symvalcomp(void *thunk, const void *a1, const void *a2)
{
int fd;
char dbg_path[PATH_MAX];
struct symtab *symtab;
GElf_Sym sym1, sym2;
u_int i1, i2;
int ret;
snprintf(dbg_path, sizeof(dbg_path),
"/usr/lib/debug/%s.debug", path);
fd = open(dbg_path, O_RDONLY);
if (fd >= 0)
return (fd);
i1 = *(const u_int *)a1;
i2 = *(const u_int *)a2;
symtab = thunk;
(void)gelf_getsym(symtab->data, i1, &sym1);
(void)gelf_getsym(symtab->data, i2, &sym2);
if (sym1.st_value < sym2.st_value)
ret = -1;
else if (sym1.st_value == sym2.st_value)
ret = 0;
else
return (open(path, O_RDONLY));
ret = 1;
return (ret);
}
static int
load_symtab(Elf *e, struct symtab *symtab, u_long sh_type)
{
GElf_Ehdr ehdr;
GElf_Shdr shdr;
Elf_Scn *scn;
u_int nsyms;
if (gelf_getehdr(e, &ehdr) == NULL)
return (-1);
scn = NULL;
while ((scn = elf_nextscn(e, scn)) != NULL) {
(void)gelf_getshdr(scn, &shdr);
if (shdr.sh_type == sh_type)
break;
}
if (scn == NULL)
return (-1);
if ((symtab->data = elf_getdata(scn, NULL)) == NULL)
return (-1);
nsyms = shdr.sh_size / shdr.sh_entsize;
symtab->index = calloc(nsyms, sizeof(u_int));
if (symtab->index == NULL)
return (-1);
for (u_int i = 0; i < nsyms; i++)
symtab->index[i] = i;
qsort_r(symtab->index, nsyms, sizeof(u_int), symtab, symvalcomp);
symtab->nsyms = nsyms;
symtab->stridx = shdr.sh_link;
return (0);
}
static void
proc_rdl2prmap(rd_loadobj_t *rdl, prmap_t *map)
load_symtabs(struct file_info *file)
{
map->pr_vaddr = rdl->rdl_saddr;
map->pr_size = rdl->rdl_eaddr - rdl->rdl_saddr;
map->pr_offset = rdl->rdl_offset;
map->pr_mflags = 0;
if (rdl->rdl_prot & RD_RDL_R)
map->pr_mflags |= MA_READ;
if (rdl->rdl_prot & RD_RDL_W)
map->pr_mflags |= MA_WRITE;
if (rdl->rdl_prot & RD_RDL_X)
map->pr_mflags |= MA_EXEC;
strlcpy(map->pr_mapname, rdl->rdl_path,
sizeof(map->pr_mapname));
file->symtab.nsyms = file->dynsymtab.nsyms = 0;
(void)load_symtab(file->elf, &file->symtab, SHT_SYMTAB);
(void)load_symtab(file->elf, &file->dynsymtab, SHT_DYNSYM);
}
static int
open_debug_file(char *path, const char *debugfile, uint32_t crc)
{
size_t n;
uint32_t compcrc;
int fd;
fd = -1;
if ((n = strlcat(path, "/", PATH_MAX)) >= PATH_MAX)
return (fd);
if (strlcat(path, debugfile, PATH_MAX) >= PATH_MAX)
goto out;
if ((fd = open(path, O_RDONLY | O_CLOEXEC)) < 0)
goto out;
if (crc32_file(fd, &compcrc) != 0 || crc != compcrc) {
DPRINTFX("ERROR: CRC32 mismatch for %s", path);
(void)close(fd);
fd = -1;
}
out:
path[n] = '\0';
return (fd);
}
/*
* Obtain an ELF descriptor for the specified mapped object. If a GNU debuglink
* section is present, a descriptor for the corresponding debug file is
* returned.
*/
static int
open_object(struct map_info *mapping)
{
char path[PATH_MAX];
GElf_Shdr shdr;
Elf *e, *e2;
Elf_Data *data;
Elf_Scn *scn;
struct file_info *file;
prmap_t *map;
const char *debugfile, *scnname;
size_t ndx;
uint32_t crc;
int fd, fd2;
if (mapping->map.pr_mapname[0] == '\0')
return (-1); /* anonymous object */
if (mapping->file->elf != NULL)
return (0); /* already loaded */
file = mapping->file;
map = &mapping->map;
if ((fd = open(map->pr_mapname, O_RDONLY | O_CLOEXEC)) < 0) {
DPRINTF("ERROR: open %s failed", map->pr_mapname);
return (-1);
}
if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1));
goto err;
}
if (gelf_getehdr(e, &file->ehdr) != &file->ehdr) {
DPRINTFX("ERROR: elf_getehdr() failed: %s", elf_errmsg(-1));
goto err;
}
scn = NULL;
while ((scn = elf_nextscn(e, scn)) != NULL) {
if (gelf_getshdr(scn, &shdr) != &shdr) {
DPRINTFX("ERROR: gelf_getshdr failed: %s",
elf_errmsg(-1));
goto err;
}
if (shdr.sh_type != SHT_PROGBITS)
continue;
if (elf_getshdrstrndx(e, &ndx) != 0) {
DPRINTFX("ERROR: elf_getshdrstrndx failed: %s",
elf_errmsg(-1));
goto err;
}
if ((scnname = elf_strptr(e, ndx, shdr.sh_name)) == NULL)
continue;
if (strcmp(scnname, ".gnu_debuglink") == 0)
break;
}
if (scn == NULL)
goto internal;
if ((data = elf_getdata(scn, NULL)) == NULL) {
DPRINTFX("ERROR: elf_getdata failed: %s", elf_errmsg(-1));
goto err;
}
/*
* The data contains a null-terminated file name followed by a 4-byte
* CRC.
*/
if (data->d_size < sizeof(crc) + 1) {
DPRINTFX("ERROR: debuglink section is too small (%zd bytes)",
data->d_size);
goto internal;
}
if (strnlen(data->d_buf, data->d_size) >= data->d_size - sizeof(crc)) {
DPRINTFX("ERROR: no null-terminator in gnu_debuglink section");
goto internal;
}
debugfile = data->d_buf;
memcpy(&crc, (char *)data->d_buf + data->d_size - sizeof(crc),
sizeof(crc));
/*
* Search for the debug file using the algorithm described in the gdb
* documentation:
* - look in the directory containing the object,
* - look in the subdirectory ".debug" of the directory containing the
* object,
* - look in the global debug directories (currently /usr/lib/debug).
*/
(void)strlcpy(path, map->pr_mapname, sizeof(path));
(void)dirname(path);
if ((fd2 = open_debug_file(path, debugfile, crc)) >= 0)
goto external;
if (strlcat(path, "/.debug", sizeof(path)) < sizeof(path) &&
(fd2 = open_debug_file(path, debugfile, crc)) >= 0)
goto external;
(void)snprintf(path, sizeof(path), PATH_DEBUG_DIR);
if (strlcat(path, map->pr_mapname, sizeof(path)) < sizeof(path)) {
(void)dirname(path);
if ((fd2 = open_debug_file(path, debugfile, crc)) >= 0)
goto external;
}
internal:
/* We didn't find a debug file, just return the object's descriptor. */
file->elf = e;
file->fd = fd;
load_symtabs(file);
return (0);
external:
if ((e2 = elf_begin(fd2, ELF_C_READ, NULL)) == NULL) {
DPRINTFX("ERROR: elf_begin failed: %s", elf_errmsg(-1));
(void)close(fd2);
goto err;
}
(void)elf_end(e);
(void)close(fd);
file->elf = e2;
file->fd = fd2;
load_symtabs(file);
return (0);
err:
if (e != NULL)
(void)elf_end(e);
(void)close(fd);
return (-1);
}
char *
proc_objname(struct proc_handle *p, uintptr_t addr, char *objname,
size_t objnamesz)
{
prmap_t *map;
size_t i;
rd_loadobj_t *rdl;
for (i = 0; i < p->nobjs; i++) {
rdl = &p->rdobjs[i];
if (addr >= rdl->rdl_saddr && addr < rdl->rdl_eaddr) {
strlcpy(objname, rdl->rdl_path, objnamesz);
for (i = 0; i < p->nmappings; i++) {
map = &p->mappings[i].map;
if (addr >= map->pr_vaddr &&
addr < map->pr_vaddr + map->pr_size) {
strlcpy(objname, map->pr_mapname, objnamesz);
return (objname);
}
}
return (NULL);
}
prmap_t *
proc_obj2map(struct proc_handle *p, const char *objname)
{
size_t i;
prmap_t *map;
rd_loadobj_t *rdl;
char path[MAXPATHLEN];
rdl = NULL;
for (i = 0; i < p->nobjs; i++) {
basename_r(p->rdobjs[i].rdl_path, path);
if (strcmp(path, objname) == 0) {
rdl = &p->rdobjs[i];
break;
}
}
if (rdl == NULL) {
if (strcmp(objname, "a.out") == 0 && p->rdexec != NULL)
rdl = p->rdexec;
else
return (NULL);
}
if ((map = malloc(sizeof(*map))) == NULL)
return (NULL);
proc_rdl2prmap(rdl, map);
return (map);
}
int
proc_iter_objs(struct proc_handle *p, proc_map_f *func, void *cd)
{
char last[MAXPATHLEN], path[MAXPATHLEN], *base;
prmap_t *map;
size_t i;
rd_loadobj_t *rdl;
prmap_t map;
char path[MAXPATHLEN];
char last[MAXPATHLEN];
int error;
if (p->nobjs == 0)
if (p->nmappings == 0)
if (proc_rdagent(p) == NULL)
return (-1);
error = 0;
memset(last, 0, sizeof(last));
for (i = 0; i < p->nobjs; i++) {
rdl = &p->rdobjs[i];
proc_rdl2prmap(rdl, &map);
basename_r(rdl->rdl_path, path);
for (i = 0; i < p->nmappings; i++) {
map = &p->mappings[i].map;
strlcpy(path, map->pr_mapname, sizeof(path));
base = basename(path);
/*
* We shouldn't call the callback twice with the same object.
* To do that we are assuming the fact that if there are
* repeated object names (i.e. different mappings for the
* same object) they occur next to each other.
*/
if (strcmp(path, last) == 0)
if (strcmp(base, last) == 0)
continue;
if ((error = (*func)(cd, &map, path)) != 0)
if ((error = (*func)(cd, map, base)) != 0)
break;
strlcpy(last, path, sizeof(last));
}
return (error);
}
static struct map_info *
_proc_addr2map(struct proc_handle *p, uintptr_t addr)
{
struct map_info *mapping;
size_t i;
if (p->nmappings == 0)
if (proc_rdagent(p) == NULL)
return (NULL);
for (i = 0; i < p->nmappings; i++) {
mapping = &p->mappings[i];
if (addr >= mapping->map.pr_vaddr &&
addr < mapping->map.pr_vaddr + mapping->map.pr_size)
return (mapping);
}
return (NULL);
}
prmap_t *
proc_addr2map(struct proc_handle *p, uintptr_t addr)
{
size_t i;
int cnt, lastvn = 0;
prmap_t *map;
rd_loadobj_t *rdl;
struct kinfo_vmentry *kves, *kve;
/*
* If we don't have a cache of listed objects, we need to query
* it ourselves.
*/
if (p->nobjs == 0) {
if ((kves = kinfo_getvmmap(p->pid, &cnt)) == NULL)
return (NULL);
for (i = 0; i < (size_t)cnt; i++) {
kve = kves + i;
if (kve->kve_type == KVME_TYPE_VNODE)
lastvn = i;
if (addr >= kve->kve_start && addr < kve->kve_end) {
if ((map = malloc(sizeof(*map))) == NULL) {
free(kves);
return (NULL);
}
map->pr_vaddr = kve->kve_start;
map->pr_size = kve->kve_end - kve->kve_start;
map->pr_offset = kve->kve_offset;
map->pr_mflags = 0;
if (kve->kve_protection & KVME_PROT_READ)
map->pr_mflags |= MA_READ;
if (kve->kve_protection & KVME_PROT_WRITE)
map->pr_mflags |= MA_WRITE;
if (kve->kve_protection & KVME_PROT_EXEC)
map->pr_mflags |= MA_EXEC;
if (kve->kve_flags & KVME_FLAG_COW)
map->pr_mflags |= MA_COW;
if (kve->kve_flags & KVME_FLAG_NEEDS_COPY)
map->pr_mflags |= MA_NEEDS_COPY;
if (kve->kve_flags & KVME_FLAG_NOCOREDUMP)
map->pr_mflags |= MA_NOCOREDUMP;
strlcpy(map->pr_mapname, kves[lastvn].kve_path,
sizeof(map->pr_mapname));
free(kves);
return (map);
}
}
free(kves);
return (NULL);
}
for (i = 0; i < p->nobjs; i++) {
rdl = &p->rdobjs[i];
if (addr >= rdl->rdl_saddr && addr < rdl->rdl_eaddr) {
if ((map = malloc(sizeof(*map))) == NULL)
return (NULL);
proc_rdl2prmap(rdl, map);
return (map);
}
}
return (NULL);
return (&_proc_addr2map(p, addr)->map);
}
/*
* Look up the symbol at addr, returning a copy of the symbol and its name.
* Look up the symbol at addr using a binary search, returning a copy of the
* symbol and its name.
*/
static int
lookup_addr(Elf *e, Elf_Scn *scn, u_long stridx, uintptr_t off, uintptr_t addr,
const char **name, GElf_Sym *symcopy)
lookup_symbol_by_addr(Elf *elf, struct symtab *symtab, uintptr_t addr,
const char **namep, GElf_Sym *sym)
{
GElf_Sym sym;
Elf_Data *data;
const char *s;
uint64_t rsym;
int i;
int min, max, mid;
if ((data = elf_getdata(scn, NULL)) == NULL) {
DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
return (1);
}
for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) {
rsym = off + sym.st_value;
if (addr >= rsym && addr < rsym + sym.st_size) {
s = elf_strptr(e, stridx, sym.st_name);
if (s != NULL) {
*name = s;
memcpy(symcopy, &sym, sizeof(*symcopy));
/*
* DTrace expects the st_value to contain
* only the address relative to the start of
* the function.
*/
symcopy->st_value = rsym;
data = symtab->data;
min = 0;
max = symtab->nsyms - 1;
while (min <= max) {
mid = (max + min) / 2;
(void)gelf_getsym(data, symtab->index[mid], sym);
if (addr >= sym->st_value &&
addr < sym->st_value + sym->st_size) {
s = elf_strptr(elf, symtab->stridx, sym->st_name);
if (s != NULL && namep != NULL)
*namep = s;
return (0);
}
if (addr < sym->st_value)
max = mid - 1;
else
min = mid + 1;
}
}
return (1);
return (ENOENT);
}
int
proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
size_t namesz, GElf_Sym *symcopy)
{
GElf_Ehdr ehdr;
GElf_Shdr shdr;
Elf *e;
Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL;
prmap_t *map;
struct file_info *file;
struct map_info *mapping;
const char *s;
uintptr_t off;
u_long symtabstridx = 0, dynsymstridx = 0;
int fd, error = -1;
int error;
if ((map = proc_addr2map(p, addr)) == NULL)
if ((mapping = _proc_addr2map(p, addr)) == NULL) {
DPRINTFX("ERROR: proc_addr2map failed to resolve 0x%jx", addr);
return (-1);
if ((fd = find_dbg_obj(map->pr_mapname)) < 0) {
DPRINTF("ERROR: open %s failed", map->pr_mapname);
goto err0;
}
if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1));
goto err1;
}
if (gelf_getehdr(e, &ehdr) == NULL) {
DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1));
goto err2;
if (open_object(mapping) != 0) {
DPRINTFX("ERROR: failed to open object %s",
mapping->map.pr_mapname);
return (-1);
}
/*
* Find the index of the STRTAB and SYMTAB sections to locate
* symbol names.
*/
scn = NULL;
while ((scn = elf_nextscn(e, scn)) != NULL) {
gelf_getshdr(scn, &shdr);
switch (shdr.sh_type) {
case SHT_SYMTAB:
symtabscn = scn;
symtabstridx = shdr.sh_link;
break;
case SHT_DYNSYM:
dynsymscn = scn;
dynsymstridx = shdr.sh_link;
break;
}
}
file = mapping->file;
off = file->ehdr.e_type == ET_DYN ? mapping->map.pr_vaddr : 0;
if (addr < off)
return (ENOENT);
addr -= off;
off = ehdr.e_type == ET_EXEC ? 0 : map->pr_vaddr;
/*
* First look up the symbol in the dynsymtab, and fall back to the
* symtab if the lookup fails.
*/
error = lookup_addr(e, dynsymscn, dynsymstridx, off, addr, &s, symcopy);
if (error == 0)
goto out;
error = lookup_addr(e, symtabscn, symtabstridx, off, addr, &s, symcopy);
if (error != 0)
goto err2;
out:
error = lookup_symbol_by_addr(file->elf, &file->dynsymtab, addr, &s,
symcopy);
if (error == ENOENT)
error = lookup_symbol_by_addr(file->elf, &file->symtab, addr,
&s, symcopy);
if (error == 0) {
symcopy->st_value += off;
demangle(s, name, namesz);
err2:
elf_end(e);
err1:
close(fd);
err0:
free(map);
}
return (error);
}
static struct map_info *
_proc_name2map(struct proc_handle *p, const char *name)
{
char path[MAXPATHLEN], *base;
struct map_info *mapping;
size_t i, len;
if ((len = strlen(name)) == 0)
return (NULL);
if (p->nmappings == 0)
if (proc_rdagent(p) == NULL)
return (NULL);
for (i = 0; i < p->nmappings; i++) {
mapping = &p->mappings[i];
(void)strlcpy(path, mapping->map.pr_mapname, sizeof(path));
base = basename(path);
if (strcmp(base, name) == 0)
return (mapping);
}
/* If we didn't find a match, try matching prefixes of the basename. */
for (i = 0; i < p->nmappings; i++) {
strlcpy(path, p->mappings[i].map.pr_mapname, sizeof(path));
base = basename(path);
if (strncmp(base, name, len) == 0)
return (&p->mappings[i]);
}
if (strcmp(name, "a.out") == 0)
return (_proc_addr2map(p, p->exec_map->pr_vaddr));
return (NULL);
}
prmap_t *
proc_name2map(struct proc_handle *p, const char *name)
{
size_t i;
int cnt;
prmap_t *map = NULL;
char tmppath[MAXPATHLEN];
struct kinfo_vmentry *kves, *kve;
rd_loadobj_t *rdl;
/*
* If we haven't iterated over the list of loaded objects,
* librtld_db isn't yet initialized and it's very likely
* that librtld_db called us. We need to do the heavy
* lifting here to find the symbol librtld_db is looking for.
*/
if (p->nobjs == 0) {
if ((kves = kinfo_getvmmap(proc_getpid(p), &cnt)) == NULL)
return (NULL);
for (i = 0; i < (size_t)cnt; i++) {
kve = kves + i;
basename_r(kve->kve_path, tmppath);
if (strcmp(tmppath, name) == 0) {
map = proc_addr2map(p, kve->kve_start);
break;
}
}
free(kves);
} else
for (i = 0; i < p->nobjs; i++) {
rdl = &p->rdobjs[i];
basename_r(rdl->rdl_path, tmppath);
if (strcmp(tmppath, name) == 0) {
if ((map = malloc(sizeof(*map))) == NULL)
return (NULL);
proc_rdl2prmap(rdl, map);
break;
}
}
if (map == NULL && strcmp(name, "a.out") == 0 && p->rdexec != NULL)
map = proc_addr2map(p, p->rdexec->rdl_saddr);
return (map);
return (&_proc_name2map(p, name)->map);
}
/*
* Look up the symbol with the given name and return a copy of it.
*/
static int
lookup_name(Elf *e, Elf_Scn *scn, u_long stridx, const char *symbol,
lookup_symbol_by_name(Elf *elf, struct symtab *symtab, const char *symbol,
GElf_Sym *symcopy, prsyminfo_t *si)
{
GElf_Sym sym;
@ -425,12 +529,11 @@ lookup_name(Elf *e, Elf_Scn *scn, u_long stridx, const char *symbol,
char *s;
int i;
if ((data = elf_getdata(scn, NULL)) == NULL) {
DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
return (1);
}
if (symtab->nsyms == 0)
return (ENOENT);
data = symtab->data;
for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) {
s = elf_strptr(e, stridx, sym.st_name);
s = elf_strptr(elf, symtab->stridx, sym.st_name);
if (s != NULL && strcmp(s, symbol) == 0) {
memcpy(symcopy, &sym, sizeof(*symcopy));
if (si != NULL)
@ -438,80 +541,38 @@ lookup_name(Elf *e, Elf_Scn *scn, u_long stridx, const char *symbol,
return (0);
}
}
return (1);
return (ENOENT);
}
int
proc_name2sym(struct proc_handle *p, const char *object, const char *symbol,
GElf_Sym *symcopy, prsyminfo_t *si)
{
Elf *e;
Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL;
GElf_Shdr shdr;
GElf_Ehdr ehdr;
prmap_t *map;
struct file_info *file;
struct map_info *mapping;
uintptr_t off;
u_long symtabstridx = 0, dynsymstridx = 0;
int fd, error = -1;
int error;
if ((map = proc_name2map(p, object)) == NULL) {
DPRINTFX("ERROR: couldn't find object %s", object);
goto err0;
}
if ((fd = find_dbg_obj(map->pr_mapname)) < 0) {
DPRINTF("ERROR: open %s failed", map->pr_mapname);
goto err0;
}
if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1));
goto err1;
}
if (gelf_getehdr(e, &ehdr) == NULL) {
DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1));
goto err2;
}
/*
* Find the index of the STRTAB and SYMTAB sections to locate
* symbol names.
*/
scn = NULL;
while ((scn = elf_nextscn(e, scn)) != NULL) {
gelf_getshdr(scn, &shdr);
switch (shdr.sh_type) {
case SHT_SYMTAB:
symtabscn = scn;
symtabstridx = shdr.sh_link;
break;
case SHT_DYNSYM:
dynsymscn = scn;
dynsymstridx = shdr.sh_link;
break;
if ((mapping = _proc_name2map(p, object)) == NULL) {
DPRINTFX("ERROR: proc_name2map failed to resolve %s", object);
return (-1);
}
if (open_object(mapping) != 0) {
DPRINTFX("ERROR: failed to open object %s",
mapping->map.pr_mapname);
return (-1);
}
/*
* First look up the symbol in the dynsymtab, and fall back to the
* symtab if the lookup fails.
*/
error = lookup_name(e, dynsymscn, dynsymstridx, symbol, symcopy, si);
file = mapping->file;
off = file->ehdr.e_type == ET_DYN ? mapping->map.pr_vaddr : 0;
error = lookup_symbol_by_name(file->elf, &file->dynsymtab, symbol,
symcopy, si);
if (error == ENOENT)
error = lookup_symbol_by_name(file->elf, &file->symtab, symbol,
symcopy, si);
if (error == 0)
goto out;
error = lookup_name(e, symtabscn, symtabstridx, symbol, symcopy, si);
if (error == 0)
goto out;
out:
off = ehdr.e_type == ET_EXEC ? 0 : map->pr_vaddr;
symcopy->st_value += off;
err2:
elf_end(e);
err1:
close(fd);
err0:
free(map);
return (error);
}
@ -527,7 +588,6 @@ proc_name2ctf(struct proc_handle *p, const char *name)
return (NULL);
ctf = ctf_open(map->pr_mapname, &error);
free(map);
return (ctf);
#else
(void)p;
@ -540,56 +600,30 @@ int
proc_iter_symbyaddr(struct proc_handle *p, const char *object, int which,
int mask, proc_sym_f *func, void *cd)
{
Elf *e;
int i, fd;
prmap_t *map;
Elf_Scn *scn, *foundscn = NULL;
Elf_Data *data;
GElf_Ehdr ehdr;
GElf_Shdr shdr;
GElf_Sym sym;
unsigned long stridx = -1;
char *s;
int error = -1;
struct file_info *file;
struct map_info *mapping;
struct symtab *symtab;
const char *s;
int error, i;
if ((map = proc_name2map(p, object)) == NULL)
if ((mapping = _proc_name2map(p, object)) == NULL) {
DPRINTFX("ERROR: proc_name2map failed to resolve %s", object);
return (-1);
if ((fd = find_dbg_obj(map->pr_mapname)) < 0) {
DPRINTF("ERROR: open %s failed", map->pr_mapname);
goto err0;
}
if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1));
goto err1;
}
if (gelf_getehdr(e, &ehdr) == NULL) {
DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1));
goto err2;
}
/*
* Find the section we are looking for.
*/
scn = NULL;
while ((scn = elf_nextscn(e, scn)) != NULL) {
gelf_getshdr(scn, &shdr);
if (which == PR_SYMTAB &&
shdr.sh_type == SHT_SYMTAB) {
foundscn = scn;
break;
} else if (which == PR_DYNSYM &&
shdr.sh_type == SHT_DYNSYM) {
foundscn = scn;
break;
}
}
if (!foundscn)
if (open_object(mapping) != 0) {
DPRINTFX("ERROR: failed to open object %s",
mapping->map.pr_mapname);
return (-1);
stridx = shdr.sh_link;
if ((data = elf_getdata(foundscn, NULL)) == NULL) {
DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
goto err2;
}
for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) {
file = mapping->file;
symtab = which == PR_SYMTAB ? &file->symtab : &file->dynsymtab;
if (symtab->nsyms == 0)
return (-1);
error = 0;
for (i = 0; gelf_getsym(symtab->data, i, &sym) != NULL; i++) {
if (GELF_ST_BIND(sym.st_info) == STB_LOCAL &&
(mask & BIND_LOCAL) == 0)
continue;
@ -614,18 +648,11 @@ proc_iter_symbyaddr(struct proc_handle *p, const char *object, int which,
if (GELF_ST_TYPE(sym.st_info) == STT_FILE &&
(mask & TYPE_FILE) == 0)
continue;
s = elf_strptr(e, stridx, sym.st_name);
if (ehdr.e_type != ET_EXEC)
sym.st_value += map->pr_vaddr;
s = elf_strptr(file->elf, symtab->stridx, sym.st_name);
if (file->ehdr.e_type == ET_DYN)
sym.st_value += mapping->map.pr_vaddr;
if ((error = (*func)(cd, &sym, s)) != 0)
goto err2;
break;
}
error = 0;
err2:
elf_end(e);
err1:
close(fd);
err0:
free(map);
return (error);
}

View File

@ -26,18 +26,21 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <err.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include "_libproc.h"
int
@ -58,14 +61,17 @@ proc_clearflags(struct proc_handle *phdl, int mask)
int
proc_continue(struct proc_handle *phdl)
{
int pending = 0;
int pending;
if (phdl == NULL)
return (-1);
if (phdl->status == PS_STOP && WSTOPSIG(phdl->wstat) != SIGTRAP)
pending = WSTOPSIG(phdl->wstat);
if (ptrace(PT_CONTINUE, phdl->pid, (caddr_t)(uintptr_t)1, pending) != 0)
else
pending = 0;
if (ptrace(PT_CONTINUE, proc_getpid(phdl), (caddr_t)(uintptr_t)1,
pending) != 0)
return (-1);
phdl->status = PS_RUN;
@ -77,23 +83,29 @@ int
proc_detach(struct proc_handle *phdl, int reason)
{
int status;
pid_t pid;
if (phdl == NULL)
return (EINVAL);
if (reason == PRELEASE_HANG)
return (EINVAL);
if (reason == PRELEASE_KILL) {
kill(phdl->pid, SIGKILL);
return (0);
kill(proc_getpid(phdl), SIGKILL);
goto free;
}
if (ptrace(PT_DETACH, phdl->pid, 0, 0) != 0 && errno == ESRCH)
return (0);
if ((phdl->flags & PATTACH_RDONLY) != 0)
goto free;
pid = proc_getpid(phdl);
if (ptrace(PT_DETACH, pid, 0, 0) != 0 && errno == ESRCH)
goto free;
if (errno == EBUSY) {
kill(phdl->pid, SIGSTOP);
waitpid(phdl->pid, &status, WUNTRACED);
ptrace(PT_DETACH, phdl->pid, 0, 0);
kill(phdl->pid, SIGCONT);
return (0);
kill(pid, SIGSTOP);
waitpid(pid, &status, WUNTRACED);
ptrace(PT_DETACH, pid, 0, 0);
kill(pid, SIGCONT);
}
free:
proc_free(phdl);
return (0);
}
@ -129,16 +141,6 @@ proc_state(struct proc_handle *phdl)
return (phdl->status);
}
pid_t
proc_getpid(struct proc_handle *phdl)
{
if (phdl == NULL)
return (-1);
return (phdl->pid);
}
int
proc_getmodel(struct proc_handle *phdl)
{
@ -156,7 +158,7 @@ proc_wstatus(struct proc_handle *phdl)
if (phdl == NULL)
return (-1);
if (waitpid(phdl->pid, &status, WUNTRACED) < 0) {
if (waitpid(proc_getpid(phdl), &status, WUNTRACED) < 0) {
if (errno != EINTR)
DPRINTF("waitpid");
return (-1);
@ -201,7 +203,7 @@ proc_read(struct proc_handle *phdl, void *buf, size_t size, size_t addr)
piod.piod_addr = (void *)buf;
piod.piod_offs = (void *)addr;
if (ptrace(PT_IO, phdl->pid, (caddr_t)&piod, 0) < 0)
if (ptrace(PT_IO, proc_getpid(phdl), (caddr_t)&piod, 0) < 0)
return (-1);
return (piod.piod_len);
}
@ -215,7 +217,7 @@ proc_getlwpstatus(struct proc_handle *phdl)
if (phdl == NULL)
return (NULL);
if (ptrace(PT_LWPINFO, phdl->pid, (caddr_t)&lwpinfo,
if (ptrace(PT_LWPINFO, proc_getpid(phdl), (caddr_t)&lwpinfo,
sizeof(lwpinfo)) < 0)
return (NULL);
siginfo = &lwpinfo.pl_siginfo;

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2014, 2015 Mark Johnston <markj@FreeBSD.org>
* Copyright (c) 2014-2016 Mark Johnston <markj@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -152,38 +152,6 @@ verify_bkpt(struct proc_handle *phdl, GElf_Sym *sym, const char *symname,
"expected map name '%s' doesn't match '%s'", mapname, mapbname);
}
ATF_TC(map_alias_obj2map);
ATF_TC_HEAD(map_alias_obj2map, tc)
{
atf_tc_set_md_var(tc, "descr",
"Callers are supposed to be able to use \"a.out\" as an alias for "
"the program executable. Make sure that proc_obj2map() handles "
"this properly.");
}
ATF_TC_BODY(map_alias_obj2map, tc)
{
struct proc_handle *phdl;
prmap_t *map1, *map2;
phdl = start_prog(tc, false);
/* Initialize the rtld_db handle. */
(void)proc_rdagent(phdl);
/* Ensure that "target_prog" and "a.out" return the same map. */
map1 = proc_obj2map(phdl, target_prog_file);
ATF_REQUIRE_MSG(map1 != NULL, "failed to look up map for '%s'",
target_prog_file);
map2 = proc_obj2map(phdl, aout_object);
ATF_REQUIRE_MSG(map2 != NULL, "failed to look up map for '%s'",
aout_object);
ATF_CHECK_EQ(strcmp(map1->pr_mapname, map2->pr_mapname), 0);
ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
proc_free(phdl);
}
ATF_TC(map_alias_name2map);
ATF_TC_HEAD(map_alias_name2map, tc)
{
@ -216,6 +184,35 @@ ATF_TC_BODY(map_alias_name2map, tc)
proc_free(phdl);
}
ATF_TC(map_prefix_name2map);
ATF_TC_HEAD(map_prefix_name2map, tc)
{
atf_tc_set_md_var(tc, "descr",
"Verify that proc_name2map() returns prefix matches of the "
"basename of loaded objects if no full matches are found.");
}
ATF_TC_BODY(map_prefix_name2map, tc)
{
struct proc_handle *phdl;
prmap_t *map1, *map2;
phdl = start_prog(tc, false);
/* Initialize the rtld_db handle. */
(void)proc_rdagent(phdl);
/* Make sure that "ld-elf" and "ld-elf.so" return the same map. */
map1 = proc_name2map(phdl, "ld-elf");
ATF_REQUIRE_MSG(map1 != NULL, "failed to look up map for 'ld-elf'");
map2 = proc_name2map(phdl, "ld-elf.so");
ATF_REQUIRE_MSG(map2 != NULL, "failed to look up map for 'ld-elf.so'");
ATF_CHECK_EQ(strcmp(map1->pr_mapname, map2->pr_mapname), 0);
ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
proc_free(phdl);
}
ATF_TC(map_alias_name2sym);
ATF_TC_HEAD(map_alias_name2sym, tc)
{
@ -315,7 +312,7 @@ ATF_TC_BODY(symbol_lookup_fail, tc)
/* Initialize the rtld_db handle. */
(void)proc_rdagent(phdl);
map = proc_obj2map(phdl, target_prog_file);
map = proc_name2map(phdl, target_prog_file);
ATF_REQUIRE_MSG(map != NULL, "failed to look up map for '%s'",
target_prog_file);
@ -376,8 +373,8 @@ ATF_TC_BODY(signal_forward, tc)
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, map_alias_obj2map);
ATF_TP_ADD_TC(tp, map_alias_name2map);
ATF_TP_ADD_TC(tp, map_prefix_name2map);
ATF_TP_ADD_TC(tp, map_alias_name2sym);
ATF_TP_ADD_TC(tp, symbol_lookup);
ATF_TP_ADD_TC(tp, symbol_lookup_fail);

View File

@ -1,4 +1,4 @@
/*
/*-
* Copyright (c) 2010 The FreeBSD Foundation
* All rights reserved.
*
@ -31,7 +31,6 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/sysctl.h>
#include <sys/user.h>

Some files were not shown because too many files have changed in this diff Show More