Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ ALL_TEST_ENV_OVERRIDE := $(shell [ -n "${DD_TRACE_DOCKER_DEBUG}" ] && echo DD_TR

VERSION := $(shell cat VERSION)

INI_FILE := $(shell ASAN_OPTIONS=detect_leaks=0 php -d ddtrace.disable=1 -i | awk -F"=>" '/Scan this dir for additional .ini files/ {print $$2}')/ddtrace.ini
INI_DIR := $(shell ASAN_OPTIONS=detect_leaks=0 php -d ddtrace.disable=1 -i | awk -F"=>" '/Scan this dir for additional .ini files/ {print $$2}')
INI_FILE := $(INI_DIR)/ddtrace.ini
TRACER_SOURCES_INI := -d datadog.trace.sources_path=$(TRACER_SOURCE_DIR)

RUN_TESTS_IS_PARALLEL ?= $(shell test $(PHP_MAJOR_MINOR) -ge 74 && echo 1)
Expand Down Expand Up @@ -378,6 +379,13 @@ prod:
strict:
$(eval CFLAGS=-Wall -Werror -Wextra)

compile_profiler:
(cd profiling; CARGO_TARGET_DIR=$(PROJECT_ROOT)/tmp/build_profiler cargo build --release --features trigger_time_sample)

install_profiler: compile_profiler
cp $(PROJECT_ROOT)/tmp/build_profiler/release/libdatadog_php_profiling.so $(PHP_EXTENSION_DIR)/datadog-profiling.so
$(Q) echo "extension=datadog-profiling.so" | $(SUDO) tee $(INI_DIR)/datadog-profiling.ini

clang_find_files_to_lint:
@find . \( \
-path ./.git -prune -o \
Expand Down
4 changes: 1 addition & 3 deletions config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,7 @@ if test "$PHP_DDTRACE" != "no"; then
zend_abstract_interface/headers/headers.c \
zend_abstract_interface/hook/hook.c \
zend_abstract_interface/json/json.c \
zend_abstract_interface/symbols/lookup.c \
zend_abstract_interface/symbols/call.c \
zend_abstract_interface/sandbox/call.c \
zend_abstract_interface/uri_normalization/uri_normalization.c \
zend_abstract_interface/zai_string/string.c \
"
Expand Down Expand Up @@ -295,7 +294,6 @@ EOT

PHP_ADD_INCLUDE([$ext_srcdir/zend_abstract_interface])
PHP_ADD_BUILD_DIR([$ext_builddir/zend_abstract_interface])
PHP_ADD_BUILD_DIR([$ext_builddir/zend_abstract_interface/symbols])
PHP_ADD_BUILD_DIR([$ext_builddir/zend_abstract_interface/config])
PHP_ADD_BUILD_DIR([$ext_builddir/zend_abstract_interface/env])
PHP_ADD_BUILD_DIR([$ext_builddir/zend_abstract_interface/exceptions])
Expand Down
2 changes: 1 addition & 1 deletion config.w32
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ if (PHP_DDTRACE != 'no') {
ADD_SOURCES(zai_dirname + "/headers", "headers.c", "ddtrace");
ADD_SOURCES(zai_dirname + "/hook", "hook.c", "ddtrace");
ADD_SOURCES(zai_dirname + "/json", "json.c", "ddtrace");
ADD_SOURCES(zai_dirname + "/sandbox", "call.c", "ddtrace");
ADD_SOURCES(zai_dirname + "/zai_string", "string.c", "ddtrace");
ADD_SOURCES(zai_dirname + "/symbols", "call.c lookup.c", "ddtrace");
ADD_SOURCES(zai_dirname + "/uri_normalization", "uri_normalization.c", "ddtrace");
if (version < 800) {
ADD_SOURCES(zai_dirname + "/sandbox/php7", "sandbox.c", "ddtrace");
Expand Down
1 change: 0 additions & 1 deletion ext/autoload_php_files.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
#include "telemetry.h"
#include <components/log/log.h>
#include <sandbox/sandbox.h>
#include <symbols/symbols.h>

ZEND_EXTERN_MODULE_GLOBALS(ddtrace);

Expand Down
39 changes: 39 additions & 0 deletions ext/compatibility.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,34 @@
#define ZVAL_VARARG_PARAM(list, arg_num) (&(((zval *)list)[arg_num]))
#define IS_TRUE_P(x) (Z_TYPE_P(x) == IS_TRUE)

static zend_always_inline zend_fcall_info dd_fcall_info(int argc, zval *args, zval *rv) {
return (zend_fcall_info){
.param_count = argc,
.params = args,
.retval = rv,
.size = sizeof(zend_fcall_info),
#if PHP_VERSION_ID < 70100
.symbol_table = NULL,
#endif
#if PHP_VERSION_ID >= 80000
.named_params = NULL,
#else
.no_separation = 1,
#endif
};
}

static zend_always_inline void dd_get_closure_to_fcc(zval *closure, zend_fcall_info_cache *fcc) {
#if PHP_VERSION_ID < 70300
fcc->initialized = 1;
#endif
#if PHP_VERSION_ID < 80000
Z_OBJ_HANDLER_P(closure, get_closure)(closure, &fcc->called_scope, &fcc->function_handler, &fcc->object);
#else
Z_OBJ_HANDLER_P(closure, get_closure)(Z_OBJ_P(closure), &fcc->called_scope, &fcc->function_handler, &fcc->object, 1);
#endif
}

static inline zval *ddtrace_assign_variable(zval *variable_ptr, zval *value) {
#if PHP_VERSION_ID < 70400
return zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR);
Expand Down Expand Up @@ -305,6 +333,8 @@ static inline zend_string *zend_ini_get_value(zend_string *name) {
__fill_idx++; \
} while (0)

#define ZEND_ACC_HEAP_RT_CACHE ZEND_ACC_NO_RT_ARENA

#define DD_PARAM_ERROR_CODE error_code
#else
#define DD_PARAM_ERROR_CODE _error_code
Expand Down Expand Up @@ -430,6 +460,15 @@ static zend_always_inline void zend_array_release(zend_array *array)
}
}

static inline void *zend_hash_find_ptr_lc(const HashTable *ht, zend_string *key) {
void *result;
zend_string *lc_key = zend_string_tolower(key);
result = zend_hash_find_ptr(ht, lc_key);
zend_string_release(lc_key);
return result;
}


#define ZEND_UNREACHABLE() ZEND_ASSUME(0)

#define ZEND_ARG_SEND_MODE(arg_info) (arg_info)->pass_by_reference
Expand Down
2 changes: 1 addition & 1 deletion ext/ddtrace.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ interface Integration {
const NOT_AVAILABLE = UNKNOWN;

/** Load the integration */
public function init(): int;
public static function init(): int;
}

// phpcs:disable Generic.Files.LineLength.TooLong
Expand Down
4 changes: 2 additions & 2 deletions ext/ddtrace_arginfo.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: b0742868ab85e06a351d0f07de1ae52917b51235 */
* Stub hash: ce1dae7089d7feaf54d05157905aa9605b5f9d85 */

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_DDTrace_trace_method, 0, 3, _IS_BOOL, 0)
ZEND_ARG_TYPE_INFO(0, className, IS_STRING, 0)
Expand Down Expand Up @@ -532,7 +532,7 @@ static const zend_function_entry class_DDTrace_SpanData_methods[] = {
};

static const zend_function_entry class_DDTrace_Integration_methods[] = {
ZEND_RAW_FENTRY("init", NULL, arginfo_class_DDTrace_Integration_init, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT, NULL, NULL)
ZEND_RAW_FENTRY("init", NULL, arginfo_class_DDTrace_Integration_init, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT, NULL, NULL)
ZEND_FE_END
};

Expand Down
6 changes: 2 additions & 4 deletions ext/exception_serialize.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include "sidecar.h"
#include "live_debugger.h"
#include "ext/hash/php_hash.h"
#include <zend_abstract_interface/symbols/symbols.h>
#include <exceptions/exceptions.h>

ZEND_EXTERN_MODULE_GLOBALS(ddtrace);
Expand Down Expand Up @@ -411,13 +410,12 @@ static void ddtrace_collect_exception_debug_data(zend_object *exception, zend_st
ddog_CharSlice class_slice = DDOG_CHARSLICE_C("");
zval *class_name = zend_hash_find(Z_ARR_P(frame), ZSTR_KNOWN(ZEND_STR_CLASS));
if (class_name && Z_TYPE_P(class_name) == IS_STRING) {
ce = zai_symbol_lookup_class_global(zai_str_from_zstr(Z_STR_P(class_name)));
ce = zend_hash_find_ptr_lc(EG(class_table), Z_STR_P(class_name));
class_slice = dd_zend_string_to_CharSlice(Z_STR_P(class_name));
}
zval *func_name = zend_hash_find(Z_ARR_P(frame), ZSTR_KNOWN(ZEND_STR_FUNCTION));
if (func_name && Z_TYPE_P(func_name) == IS_STRING) {
zai_str wtf = zai_str_from_zstr(Z_STR_P(func_name));
func = zai_symbol_lookup_function(ce ? ZAI_SYMBOL_SCOPE_CLASS : ZAI_SYMBOL_SCOPE_GLOBAL, ce, &wtf);
func = zend_hash_find_ptr_lc(ce ? &ce->function_table : EG(function_table), Z_STR_P(func_name));
func_slice = dd_zend_string_to_CharSlice(Z_STR_P(func_name));
}

Expand Down
97 changes: 69 additions & 28 deletions ext/hook/uhook.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ typedef struct {
} dd_closure_list;

typedef struct {
zend_object *begin;
zend_object *end;
dd_uhook_callback begin;
dd_uhook_callback end;
bool running;
zend_long id;

Expand All @@ -56,6 +56,7 @@ typedef struct {
zval property_args;
zval property_returned;
zval property_exception;
zval property_object;
zend_ulong invocation;
zend_execute_data *execute_data;
zval *vm_stack_top;
Expand All @@ -75,6 +76,47 @@ typedef struct {
dd_hook_data *hook_data;
} dd_uhook_dynamic;

#if PHP_VERSION_ID < 70400
#define ZEND_MAP_PTR(x) x
#endif

// Only called on first call or scope change
void dd_uhook_callback_apply_scope(dd_uhook_callback *cb, zend_class_entry *scope) {
if (!cb->fcc.function_handler) {
zend_function *func = (zend_function *) zend_get_closure_method_def(cb->closure);
cb->is_static = !scope || (func->common.fn_flags & ZEND_ACC_STATIC);
if (!cb->is_static) {
memcpy(&cb->func, func, sizeof(zend_function));
int cache_size = func->op_array.cache_size;
func = &cb->func;
func->op_array.fn_flags &= ~ZEND_ACC_CLOSURE; // Otherwise we run into ZEND_CLOSURE_OBJECT() out-of-bounds reads
if (cache_size) {
func->op_array.fn_flags |= ZEND_ACC_HEAP_RT_CACHE;
ZEND_MAP_PTR(cb->func.op_array.run_time_cache) = emalloc(cache_size);
}
}
cb->fcc.function_handler = func;
#if PHP_VERSION_ID < 70300
cb->fcc.initialized = 1;
#endif
if (cb->is_static) {
cb->fcc.called_scope = func->common.scope;
return;
}
}
int cache_size = cb->func.op_array.cache_size;
cb->func.common.scope = scope;
cb->fcc.called_scope = scope;
if (cache_size) {
memset(ZEND_MAP_PTR(cb->func.op_array.run_time_cache), 0, cache_size);
}
}

#if PHP_VERSION_ID < 70400
#undef ZEND_MAP_PTR
#endif


static zend_object *dd_hook_data_create(zend_class_entry *class_type) {
dd_hook_data *hook_data = ecalloc(1, sizeof(*hook_data));
zend_object_std_init(&hook_data->std, class_type);
Expand Down Expand Up @@ -192,20 +234,18 @@ void dd_uhook_report_sandbox_error(zend_execute_data *execute_data, zend_object
})
}

static bool dd_uhook_call_hook(zend_execute_data *execute_data, zend_object *closure, dd_hook_data *hook_data) {
zval closure_zv, hook_data_zv;
ZVAL_OBJ(&closure_zv, closure);
static bool dd_uhook_call_hook(zend_execute_data *execute_data, dd_uhook_callback *callback, dd_hook_data *hook_data) {
zval hook_data_zv;
ZVAL_OBJ(&hook_data_zv, &hook_data->std);

bool has_this = getThis() != NULL;
zval rv;
zai_sandbox sandbox;
zai_sandbox_open(&sandbox);
bool success = zai_symbol_call(has_this ? ZAI_SYMBOL_SCOPE_OBJECT : ZAI_SYMBOL_SCOPE_GLOBAL, has_this ? &EX(This) : NULL,
ZAI_SYMBOL_FUNCTION_CLOSURE, &closure_zv,
&rv, 1 | ZAI_SYMBOL_SANDBOX, &sandbox, &hook_data_zv);
dd_uhook_callback_ensure_scope(callback, execute_data);
zend_fcall_info fci = dd_fcall_info(1, &hook_data_zv, &rv);
bool success = zai_sandbox_call(&sandbox, &fci, &callback->fcc);
if (!success || PG(last_error_message)) {
dd_uhook_report_sandbox_error(execute_data, closure);
dd_uhook_report_sandbox_error(execute_data, callback->closure);
}
zai_sandbox_close(&sandbox);
zval_ptr_dtor(&rv);
Expand Down Expand Up @@ -297,8 +337,11 @@ static bool dd_uhook_begin(zend_ulong invocation, zend_execute_data *execute_dat
} else {
ZVAL_ARR(&dyn->hook_data->property_args, dd_uhook_collect_args(execute_data));
}
if (hasThis()) {
ZVAL_OBJ_COPY(&dyn->hook_data->property_object, Z_OBJ(EX(This)));
}

if (def->begin && !def->running) {
if (def->begin.closure && !def->running) {
dyn->hook_data->execute_data = execute_data;
// We support it for PHP 8 for now, given we need this for PHP 8.1+ right now.
// Bringing it to PHP 7.1-7.4 is possible, but not done yet.
Expand All @@ -310,10 +353,10 @@ static bool dd_uhook_begin(zend_ulong invocation, zend_execute_data *execute_dat
}
#endif

LOGEV(HOOK_TRACE, dd_uhook_log_invocation(log, execute_data, "begin", def->begin););
LOGEV(HOOK_TRACE, dd_uhook_log_invocation(log, execute_data, "begin", def->begin.closure););

def->running = true;
dd_uhook_call_hook(execute_data, def->begin, dyn->hook_data);
dd_uhook_call_hook(execute_data, &def->begin, dyn->hook_data);
def->running = false;
dyn->hook_data->retval_ptr = NULL;
}
Expand Down Expand Up @@ -395,7 +438,7 @@ static void dd_uhook_end(zend_ulong invocation, zend_execute_data *execute_data,

bool keep_span = true;

if (def->end && !def->running && get_DD_TRACE_ENABLED()) {
if (def->end.closure && !def->running && get_DD_TRACE_ENABLED()) {
zval tmp;

/* If the profiler doesn't handle a potential pending interrupt before
Expand Down Expand Up @@ -432,11 +475,11 @@ static void dd_uhook_end(zend_ulong invocation, zend_execute_data *execute_data,
}
zval_ptr_dtor(&tmp);

LOGEV(HOOK_TRACE, dd_uhook_log_invocation(log, execute_data, "end", def->end););
LOGEV(HOOK_TRACE, dd_uhook_log_invocation(log, execute_data, "end", def->end.closure););

def->running = true;
dyn->hook_data->retval_ptr = retval;
keep_span = dd_uhook_call_hook(execute_data, def->end, dyn->hook_data);
keep_span = dd_uhook_call_hook(execute_data, &def->end, dyn->hook_data);
dyn->hook_data->retval_ptr = NULL;
def->running = false;
}
Expand Down Expand Up @@ -485,12 +528,8 @@ static void dd_uhook_end(zend_ulong invocation, zend_execute_data *execute_data,

static void dd_uhook_dtor(void *data) {
dd_uhook_def *def = data;
if (def->begin) {
OBJ_RELEASE(def->begin);
}
if (def->end) {
OBJ_RELEASE(def->end);
}
dd_uhook_callback_destroy(&def->begin);
dd_uhook_callback_destroy(&def->end);
if (def->function) {
zend_string_release(def->function);
if (def->scope) {
Expand Down Expand Up @@ -581,13 +620,15 @@ PHP_FUNCTION(DDTrace_install_hook) {
dd_uhook_def *def = emalloc(sizeof(*def));
def->closure = NULL;
def->running = false;
def->begin = begin ? Z_OBJ_P(begin) : NULL;
if (def->begin) {
GC_ADDREF(def->begin);
def->begin.fcc.function_handler = NULL;
def->begin.closure = begin ? Z_OBJ_P(begin) : NULL;
if (def->begin.closure) {
GC_ADDREF(def->begin.closure);
}
def->end = end ? Z_OBJ_P(end) : NULL;
if (def->end) {
GC_ADDREF(def->end);
def->end.fcc.function_handler = NULL;
def->end.closure = end ? Z_OBJ_P(end) : NULL;
if (def->end.closure) {
GC_ADDREF(def->end.closure);
}
def->id = -1;

Expand Down
Loading
Loading