return Allocate(stack, size, GetPageSizeCached(), kAlwaysClearMemory);
}
+INTERCEPTOR(SIZE_T, strlen, const char *s) {
+ return REAL(strlen)(s);
+}
+
+INTERCEPTOR(void*, memcpy, void *dst, const void *src, uptr size) {
+ return REAL(memcpy)(dst, src, size);
+}
+
+INTERCEPTOR(char*, strdup, const char *s) {
+ ENSURE_LSAN_INITED;
+ GET_STACK_TRACE_MALLOC;
+ uptr length = REAL(strlen)(s);
+ void *new_mem = Allocate(stack, length + 1, 1, kAlwaysClearMemory);
+ REAL(memcpy)(new_mem, s, length + 1);
+ return reinterpret_cast<char*>(new_mem);
+}
+
#define OPERATOR_NEW_BODY \
ENSURE_LSAN_INITED; \
GET_STACK_TRACE_MALLOC; \
INTERCEPT_FUNCTION(free);
INTERCEPT_FUNCTION(calloc);
INTERCEPT_FUNCTION(realloc);
+ INTERCEPT_FUNCTION(strdup);
INTERCEPT_FUNCTION(pthread_create);
INTERCEPT_FUNCTION(pthread_join);
+ // Just to make REAL(strlen)(...) available.
+ INTERCEPT_FUNCTION(strlen);
+ // Just to make REAL(memcpy)(...) available.
+ INTERCEPT_FUNCTION(memcpy);
+
if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) {
Report("LeakSanitizer: failed to create thread key.\n");
Die();
realloc@*; realloc; 4
calloc@*; calloc; 4
posix_memalign@*; posix_memalign; 4
+strdup@*; strdup; 4
#filename libdamemalloc.c
realloc@*; realloc; 1
calloc@*; calloc; 1
posix_memalign@*; posix_memalign; 1
+strdup@*; strdup; 1
MEM_CALLOC,
MEM_REALLOC,
MEM_FREE,
- MEM_POSIX_MEMALIGN
+ MEM_POSIX_MEMALIGN,
+ MEM_STRDUP
};
/* TODO Split LSan */
"calloc",
"realloc",
"free",
- "posix_memalign"
+ "posix_memalign",
+ "strdup"
};
/* TODO Split LSan */
"__interceptor_calloc",
"__interceptor_realloc",
"__interceptor_free",
- "__interceptor_posix_memalign"
+ "__interceptor_posix_memalign",
+ "__interceptor_strdup"
};
return iret;
}
+
+HANDLER_WRAPPERS(memory_feature, char *, strdup, const char*, s)
+{
+ /* TODO Split LSan */
+ static char* (*lsan_strdupp)(const char *);
+ char* (*strdupp)(const char *);
+ DECLARE_VARIABLE_STANDARD;
+ char *pret;
+ int size = strlen(s);
+
+ if (lsan_init_succeeded && lsan_strdupp == NULL)
+ lsan_strdupp = lsan_get_sym(lsan_interceptors[MEM_STRDUP]);
+
+ /* If LSan is used - call LSan strdup instead of origin */
+ strdupp = lsan_init_succeeded ? lsan_strdupp : (void *)orig;
+
+ PRE_PROBEBLOCK();
+
+ pret = (*strdupp)(s);
+
+ if (pret == 0)
+ add_memory_hash(pret, size, MEMTYPE_ALLOC, CALL_TYPE);
+
+ POST_PACK_PROBEBLOCK_BEGIN();
+
+ PREPARE_LOCAL_BUF();
+ PACK_COMMON_BEGIN(MSG_PROBE_MEMORY, API_ID_strdup, "x",
+ (int64_t)size);
+ PACK_COMMON_END('p', pret, newerrno, call_type, caller);
+ PACK_MEMORY(size, MEMORY_API_ALLOC, pret);
+ FLUSH_LOCAL_BUF();
+
+ POST_PACK_PROBEBLOCK_END();
+
+ return pret;
+}
X(PROBE_NAME(memset), "memset", GT_TARGET_PROBE) \
X(PROBE_NAME(memcmp), "memcmp", GT_TARGET_PROBE) \
X(PROBE_NAME(memcpy), "memcpy", GT_TARGET_PROBE) \
- X(PROBE_NAME(posix_memalign), "posix_memalign", GT_ALWAYS_PROBE)
+ X(PROBE_NAME(posix_memalign), "posix_memalign", GT_ALWAYS_PROBE) \
+ X(PROBE_NAME(strdup), "strdup", GT_ALWAYS_PROBE)
#define PROBES_LIST_MEMORY_ALWAYS \
X(CONCAT(PROBE_NAME(malloc), _always), "malloc", GT_ALWAYS_PROBE) \
X(CONCAT(PROBE_NAME(memset), _always), "memset", GT_ALWAYS_PROBE) \
X(CONCAT(PROBE_NAME(memcmp), _always), "memcmp", GT_ALWAYS_PROBE) \
X(CONCAT(PROBE_NAME(memcpy), _always), "memcpy", GT_ALWAYS_PROBE) \
- X(CONCAT(PROBE_NAME(posix_memalign), _always), "posix_memalign", GT_ALWAYS_PROBE)
+ X(CONCAT(PROBE_NAME(posix_memalign), _always), "posix_memalign", GT_ALWAYS_PROBE) \
+ X(CONCAT(PROBE_NAME(strdup), _always), "strdup", GT_ALWAYS_PROBE)
#define PROBES_LIST \
PROBES_LIST_MEMORY