details: https://hg.nginx.org/njs/rev/8fe7d9723477 branches: changeset: 1899:8fe7d9723477 user: Dmitry Volyntsev <xei...@nginx.com> date: Tue Jun 28 22:36:30 2022 -0700 description: Added native function symbolizer for function tracing in debug.
diffstat: auto/cc | 4 + auto/help | 4 + auto/libbfd | 35 ++++++ auto/link | 31 +++++ auto/openssl | 1 + auto/options | 9 + auto/pcre | 3 + auto/sources | 4 + configure | 15 +- src/njs.h | 3 + src/njs_addr2line.c | 265 +++++++++++++++++++++++++++++++++++++++++++++++ src/njs_addr2line.h | 22 +++ src/njs_function.c | 25 +++- src/njs_main.h | 1 + src/njs_shell.c | 13 ++ src/njs_sprintf.c | 6 + src/njs_vmcode.c | 6 +- src/njs_vmcode.h | 4 +- src/test/njs_unit_test.c | 43 +++++++- 19 files changed, 474 insertions(+), 20 deletions(-) diffs (736 lines): diff -r 20ee5213e3c4 -r 8fe7d9723477 auto/cc --- a/auto/cc Wed Jun 22 23:37:27 2022 -0700 +++ b/auto/cc Tue Jun 28 22:36:30 2022 -0700 @@ -177,6 +177,10 @@ if [ "$NJS_DEBUG_MEMORY" = "YES" ]; then njs_define=NJS_DEBUG_MEMORY . auto/define fi +if [ "$NJS_DEBUG_OPCODE" = "YES" ]; then + njs_define=NJS_DEBUG_OPCODE . auto/define +fi + if [ "$NJS_TEST262" = "YES" ]; then njs_define=NJS_TEST262 . auto/define fi diff -r 20ee5213e3c4 -r 8fe7d9723477 auto/help --- a/auto/help Wed Jun 22 23:37:27 2022 -0700 +++ b/auto/help Tue Jun 28 22:36:30 2022 -0700 @@ -33,10 +33,14 @@ default: "$NJS_LD_OPT" --address-sanitizer=YES enables build with address sanitizer, \ default: "$NJS_ADDRESS_SANITIZER" + --addr2line=YES enables native function symbolization, \ +default: "$NJS_ADDR2LINE" --debug=YES enables additional runtime checks, \ default: "$NJS_DEBUG" --debug-memory=YES enables memory alloc debug, \ default: "$NJS_DEBUG_MEMORY" + --debug-opcode=YES enables runtime function tracing, \ +default: "$NJS_DEBUG_OPCODE" --test262=YES enables test262 extentions, \ default: "$NJS_TEST262" END diff -r 20ee5213e3c4 -r 8fe7d9723477 auto/libbfd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/auto/libbfd Tue Jun 28 22:36:30 2022 -0700 @@ -0,0 +1,35 @@ +# Copyright (C) Dmitry Volyntsev +# Copyright (C) NGINX, Inc. + + +NJS_HAVE_LIBBFD=NO + +if [ $NJS_ADDR2LINE = YES ]; then + njs_found=no + + njs_feature="BFD library" + njs_feature_name=NJS_HAVE_LIBBFD + njs_feature_run=yes + njs_feature_incs= + njs_feature_libs="-lbfd" + njs_feature_test="#include <bfd.h> + + int main() { + bfd_init(); + return 0; + }" + . auto/feature + + if [ $njs_found = no ]; then + njs_feature="OpenSSL library -lcrypto" + njs_feature_libs="-lcrypto" + + . auto/feature + fi + + + if [ $njs_found = yes ]; then + NJS_HAVE_LIBBFD=YES + NJS_LIB_AUX_LIBS="$NJS_LIB_AUX_LIBS $njs_feature_libs" + fi +fi diff -r 20ee5213e3c4 -r 8fe7d9723477 auto/link --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/auto/link Tue Jun 28 22:36:30 2022 -0700 @@ -0,0 +1,31 @@ + +# Copyright (C) Dmitry Volyntsev +# Copyright (C) NGINX, Inc. + + +NJS_HAVE_DL_ITERATE_PHDR=NO + +if [ $NJS_ADDR2LINE = YES ]; then + njs_feature="dl_iterate_phdr()" + njs_feature_name=NJS_HAVE_DL_ITERATE_PHDR + njs_feature_run=yes + njs_feature_incs= + njs_feature_libs= + njs_feature_test="#define _GNU_SOURCE + #include <link.h> + + static int + cb(struct dl_phdr_info *info, size_t size, void *data) { + return 0; + } + + int main() { + dl_iterate_phdr(cb, 0); + return 0; + }" + . auto/feature + + if [ $njs_found = yes ]; then + NJS_HAVE_DL_ITERATE_PHDR=YES + fi +fi diff -r 20ee5213e3c4 -r 8fe7d9723477 auto/openssl --- a/auto/openssl Wed Jun 22 23:37:27 2022 -0700 +++ b/auto/openssl Tue Jun 28 22:36:30 2022 -0700 @@ -46,6 +46,7 @@ if [ $NJS_OPENSSL = YES ]; then NJS_HAVE_OPENSSL=YES NJS_OPENSSL_LIB="$njs_feature_libs" + NJS_LIB_AUX_LIBS="$NJS_LIB_AUX_LIBS $njs_feature_libs" fi fi diff -r 20ee5213e3c4 -r 8fe7d9723477 auto/options --- a/auto/options Wed Jun 22 23:37:27 2022 -0700 +++ b/auto/options Tue Jun 28 22:36:30 2022 -0700 @@ -8,7 +8,10 @@ NJS_LD_OPT=${NJS_CC_OPT:--O} NJS_DEBUG=NO NJS_DEBUG_MEMORY=NO +NJS_DEBUG_OPCODE=NO + NJS_ADDRESS_SANITIZER=NO +NJS_ADDR2LINE=NO NJS_TEST262=YES NJS_OPENSSL=YES @@ -34,8 +37,10 @@ do --build-dir=*) NJS_BUILD_DIR="$value" ;; --address-sanitizer=*) NJS_ADDRESS_SANITIZER="$value" ;; + --addr2line=*) NJS_ADDR2LINE="$value" ;; --debug=*) NJS_DEBUG="$value" ;; --debug-memory=*) NJS_DEBUG_MEMORY="$value" ;; + --debug-opcode=*) NJS_DEBUG_OPCODE="$value" ;; --test262=*) NJS_TEST262="$value" ;; --no-openssl) NJS_OPENSSL=NO ;; @@ -66,3 +71,7 @@ done if [ "$NJS_DEBUG_MEMORY" = "YES" ]; then NJS_DEBUG=YES fi + +if [ "$NJS_DEBUG_OPCODE" = "YES" ]; then + NJS_ADDR2LINE=YES +fi diff -r 20ee5213e3c4 -r 8fe7d9723477 auto/pcre --- a/auto/pcre Wed Jun 22 23:37:27 2022 -0700 +++ b/auto/pcre Tue Jun 28 22:36:30 2022 -0700 @@ -134,3 +134,6 @@ if [ $NJS_PCRE = YES ]; then fi fi + +NJS_LIB_AUX_CFLAGS="$NJS_LIB_AUX_CFLAGS $NJS_PCRE_CFLAGS" +NJS_LIB_AUX_LIBS="$NJS_LIB_AUX_LIBS $NJS_PCRE_LIB" diff -r 20ee5213e3c4 -r 8fe7d9723477 auto/sources --- a/auto/sources Wed Jun 22 23:37:27 2022 -0700 +++ b/auto/sources Tue Jun 28 22:36:30 2022 -0700 @@ -75,6 +75,10 @@ if [ "$NJS_PCRE" = "YES" ]; then NJS_LIB_SRCS="$NJS_LIB_SRCS external/njs_regex.c" fi +if [ "$NJS_HAVE_LIBBFD" = "YES" -a "$NJS_HAVE_DL_ITERATE_PHDR" = "YES" ]; then + NJS_LIB_SRCS="$NJS_LIB_SRCS src/njs_addr2line.c" +fi + NJS_TS_SRCS=$(find ts/ -name "*.d.ts" -o -name "*.json") NJS_TEST_TS_SRCS=$(find test/ts/ -name "*.ts" -o -name "*.json") diff -r 20ee5213e3c4 -r 8fe7d9723477 configure --- a/configure Wed Jun 22 23:37:27 2022 -0700 +++ b/configure Tue Jun 28 22:36:30 2022 -0700 @@ -33,6 +33,10 @@ cat << END > $NJS_AUTO_CONFIG_H END +NJS_LIBS="$NJS_LIBRT" +NJS_LIB_AUX_CFLAGS= +NJS_LIB_AUX_LIBS= + . auto/os . auto/cc . auto/types @@ -46,16 +50,11 @@ END . auto/pcre . auto/readline . auto/openssl -. auto/sources - -NJS_LIB_AUX_CFLAGS="$NJS_PCRE_CFLAGS" +. auto/libbfd +. auto/link -NJS_LIBS="$NJS_LIBRT" -NJS_LIB_AUX_LIBS="$NJS_PCRE_LIB $NJS_OPENSSL_LIB" - +. auto/sources . auto/modules . auto/make - . auto/expect - . auto/summary diff -r 20ee5213e3c4 -r 8fe7d9723477 src/njs.h --- a/src/njs.h Wed Jun 22 23:37:27 2022 -0700 +++ b/src/njs.h Tue Jun 28 22:36:30 2022 -0700 @@ -250,6 +250,9 @@ typedef struct { uint8_t unsafe; /* 1 bit */ uint8_t module; /* 1 bit */ uint8_t ast; /* 1 bit */ +#ifdef NJS_DEBUG_OPCODE + uint8_t opcode_debug; /* 1 bit */ +#endif uint8_t unhandled_rejection; } njs_vm_opt_t; diff -r 20ee5213e3c4 -r 8fe7d9723477 src/njs_addr2line.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/njs_addr2line.c Tue Jun 28 22:36:30 2022 -0700 @@ -0,0 +1,265 @@ + +/* + * Copyright (C) Dmitry Volyntsev + * Copyright (C) NGINX, Inc. + * + * addr2line impementaton based upon the work by Jeff Muizelaar. + * + * A hacky replacement for backtrace_symbols in glibc + * + * backtrace_symbols in glibc looks up symbols using dladdr which is limited in + * the symbols that it sees. libbacktracesymbols opens the executable and + * shared libraries using libbfd and will look up backtrace information using + * the symbol table and the dwarf line information. + * + * Derived from addr2line.c from GNU Binutils by Jeff Muizelaar + * + * Copyright 2007 Jeff Muizelaar + * + * addr2line.c -- convert addresses to line number and function name + * Copyright 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + * Contributed by Ulrich Lauther <ulrich.laut...@mchp.siemens.de> + * + * This file was part of GNU Binutils. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#define _GNU_SOURCE +#include <njs_main.h> +#include <njs_addr2line.h> + +#include <bfd.h> +#include <link.h> + + +typedef struct { + const char *file; + ElfW(Addr) address; + ElfW(Addr) base; + void *hdr; +} njs_file_match_t; + + +typedef struct { + bfd_vma pc; + const char *filename; + const char *functionname; + unsigned int line; + njs_bool_t found; + asymbol **syms; +} njs_translate_address_t; + + +static u_char *njs_process_file(u_char *buf, u_char *end, bfd_vma *addr, + const char *file_name); +static long njs_read_symtab(bfd *abfd, asymbol ***syms); +static u_char *njs_translate_address(u_char *buf, u_char *end, bfd_vma *addr, + bfd *abfd, asymbol **syms); +static void njs_find_address_in_section(bfd *abfd, asection *section, + void *data); +static int njs_find_matching_file(struct dl_phdr_info *info, size_t size, + void *data); + + +u_char * +_njs_addr2line(u_char *buf, u_char *end, void *address) +{ + bfd_vma addr; + const char *fname; + + njs_file_match_t match = { .address = (ElfW(Addr)) address }; + + bfd_init(); + + dl_iterate_phdr(njs_find_matching_file, &match); + + fname = "/proc/self/exe"; + if (match.file != NULL && njs_strlen(match.file)) { + fname = match.file; + } + + addr = (ElfW(Addr)) address - match.base; + + return njs_process_file(buf, end, &addr, fname); +} + + +static u_char * +njs_process_file(u_char *buf, u_char *end, bfd_vma *addr, const char *file_name) +{ + bfd *abfd; + char **matching; + u_char *p; + asymbol **syms; + + abfd = bfd_openr(file_name, NULL); + if (abfd == NULL) { + njs_stderror("%s: failed to open while looking for addr2line", + file_name); + return NULL; + } + + if (bfd_check_format(abfd, bfd_archive)) { + njs_stderror("%s: can not get addresses from archive", file_name); + return NULL; + } + + if (!bfd_check_format_matches(abfd, bfd_object, &matching)) { + njs_stderror("%s: bfd_check_format_matches() failed", + bfd_get_filename(abfd)); + return NULL; + } + + if (njs_read_symtab(abfd, &syms) <= 0) { + njs_stderror("%s: njs_read_symtab() failed", + bfd_get_filename(abfd)); + return NULL; + } + + p = njs_translate_address(buf, end, addr, abfd, syms); + + if (syms != NULL) { + free(syms); + syms = NULL; + } + + bfd_close(abfd); + + return p; +} + + +static long +njs_read_symtab(bfd *abfd, asymbol ***syms) +{ + long symcount; + unsigned size; + + if ((bfd_get_file_flags(abfd) & HAS_SYMS) == 0) { + return 0; + } + + symcount = bfd_read_minisymbols(abfd, 0, (PTR) syms, &size); + if (symcount == 0) { + symcount = bfd_read_minisymbols(abfd, 1 /* dynamic */, + (PTR) syms, &size); + } + + return symcount; +} + + +static u_char * +njs_translate_address(u_char *buf, u_char *end, bfd_vma *addr, bfd *abfd, + asymbol **syms) +{ + char *h; + const char *name; + njs_translate_address_t ctx; + + ctx.pc = *addr; + ctx.found = 0; + ctx.syms = syms; + + bfd_map_over_sections(abfd, njs_find_address_in_section, &ctx); + + if (!ctx.found) { + return njs_sprintf(buf, end, "\?\? \t\?\?:0 [0x%p]", addr); + } + + name = ctx.functionname; + + if (name == NULL || *name == '\0') { + name = "??"; + } + + if (ctx.filename != NULL) { + h = strrchr(ctx.filename, '/'); + if (h != NULL) { + ctx.filename = h + 1; + } + } + + return njs_sprintf(buf, end, "%s() %s:%ud [0x%p]", name, + ctx.filename ? ctx.filename : "??", ctx.line, addr); +} + + +static void +njs_find_address_in_section(bfd *abfd, asection *section, void *data) +{ + bfd_vma vma; + bfd_size_type size; + njs_translate_address_t *ctx; + + ctx = data; + + if (ctx->found) { + return; + } + + if ((bfd_section_flags(section) & SEC_ALLOC) == 0) { + return; + } + + vma = bfd_section_vma(section); + if (ctx->pc < vma) { + return; + } + + size = bfd_section_size(section); + if (ctx->pc >= vma + size) { + return; + } + + ctx->found = bfd_find_nearest_line(abfd, section, ctx->syms, ctx->pc - vma, + &ctx->filename, &ctx->functionname, + &ctx->line); +} + + +static int +njs_find_matching_file(struct dl_phdr_info *info, size_t size, void *data) +{ + long n; + const ElfW(Phdr) *phdr; + + ElfW(Addr) load_base = info->dlpi_addr; + njs_file_match_t *match = data; + + /* + * This code is modeled from Gfind_proc_info-lsb.c:callback() + * from libunwind. + */ + + phdr = info->dlpi_phdr; + + for (n = info->dlpi_phnum; --n >= 0; phdr++) { + if (phdr->p_type == PT_LOAD) { + ElfW(Addr) vaddr = phdr->p_vaddr + load_base; + + if (match->address >= vaddr + && match->address < vaddr + phdr->p_memsz) + { + /* we found a match */ + match->file = info->dlpi_name; + match->base = info->dlpi_addr; + } + } + } + + return 0; +} diff -r 20ee5213e3c4 -r 8fe7d9723477 src/njs_addr2line.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/njs_addr2line.h Tue Jun 28 22:36:30 2022 -0700 @@ -0,0 +1,22 @@ + +/* + * Copyright (C) Dmitry Volyntsev + * Copyright (C) Nginx, Inc. + */ + +#ifndef _NJS_ADDR2LINE_H_INCLUDED_ +#define _NJS_ADDR2LINE_H_INCLUDED_ + + + u_char *_njs_addr2line(u_char *buf, u_char *end, void *address); + + +#if defined(NJS_HAVE_LIBBFD) && defined(NJS_HAVE_DL_ITERATE_PHDR) +#define NJS_HAVE_ADDR2LINE 1 +#define njs_addr2line(buf, end, addr) _njs_addr2line(buf, end, addr) +#else +#define njs_addr2line(buf, end, addr) \ + njs_sprintf(buf, end, "\?\?() \?\?:0 [0x%p]", addr) +#endif + +#endif /* _NJS_ADDR2LINE_H_INCLUDED_ */ diff -r 20ee5213e3c4 -r 8fe7d9723477 src/njs_function.c --- a/src/njs_function.c Wed Jun 22 23:37:27 2022 -0700 +++ b/src/njs_function.c Tue Jun 28 22:36:30 2022 -0700 @@ -711,15 +711,18 @@ njs_function_native_call(njs_vm_t *vm) native = vm->top_frame; function = native->function; -#ifdef NJS_OPCODE_DEBUG - njs_str_t name; +#ifdef NJS_DEBUG_OPCODE + njs_str_t name; + + if (vm->options.opcode_debug) { - ret = njs_builtin_match_native_function(vm, function, &name); - if (ret != NJS_OK) { - name = njs_entry_unknown; - } + ret = njs_builtin_match_native_function(vm, function, &name); + if (ret != NJS_OK) { + name = njs_str_value("unmapped"); + } - njs_printf("CALL NATIVE %V\n", &name); + njs_printf("CALL NATIVE %V %P\n", &name, function->u.native); + } #endif if (njs_fast_path(function->bound == NULL)) { @@ -737,6 +740,14 @@ njs_function_native_call(njs_vm_t *vm) } ret = call(vm, native->arguments, native->nargs, function->magic8); + +#ifdef NJS_DEBUG_OPCODE + if (vm->options.opcode_debug) { + njs_printf("CALL NATIVE RETCODE: %i %V %P\n", ret, &name, + function->u.native); + } +#endif + if (njs_slow_path(ret == NJS_ERROR)) { return ret; } diff -r 20ee5213e3c4 -r 8fe7d9723477 src/njs_main.h --- a/src/njs_main.h Wed Jun 22 23:37:27 2022 -0700 +++ b/src/njs_main.h Tue Jun 28 22:36:30 2022 -0700 @@ -37,6 +37,7 @@ #include <njs_utils.h> #include <njs_sprintf.h> #include <njs_assert.h> +#include <njs_addr2line.h> #include <njs_regex.h> diff -r 20ee5213e3c4 -r 8fe7d9723477 src/njs_shell.c --- a/src/njs_shell.c Wed Jun 22 23:37:27 2022 -0700 +++ b/src/njs_shell.c Tue Jun 28 22:36:30 2022 -0700 @@ -36,6 +36,7 @@ typedef struct { uint8_t version; uint8_t ast; uint8_t unhandled_rejection; + uint8_t opcode_debug; int exit_code; char *file; @@ -272,6 +273,9 @@ main(int argc, char **argv) vm_options.sandbox = opts.sandbox; vm_options.unsafe = !opts.safe; vm_options.module = opts.module; +#ifdef NJS_DEBUG_OPCODE + vm_options.opcode_debug = opts.opcode_debug; +#endif vm_options.ops = &njs_console_ops; vm_options.addons = njs_console_addon_modules; @@ -334,6 +338,9 @@ njs_options_parse(njs_opts_t *opts, int " -d print disassembled code.\n" " -e set failure exit code.\n" " -f disabled denormals mode.\n" +#ifdef NJS_DEBUG_OPCODE + " -o enable opcode debug.\n" +#endif " -p set path prefix for modules.\n" " -q disable interactive introduction prompt.\n" " -r ignore unhandled promise rejection.\n" @@ -410,6 +417,12 @@ njs_options_parse(njs_opts_t *opts, int opts->denormals = 0; break; +#ifdef NJS_DEBUG_OPCODE + case 'o': + opts->opcode_debug = 1; + break; +#endif + case 'p': if (++i < argc) { opts->n_paths++; diff -r 20ee5213e3c4 -r 8fe7d9723477 src/njs_sprintf.c --- a/src/njs_sprintf.c Wed Jun 22 23:37:27 2022 -0700 +++ b/src/njs_sprintf.c Tue Jun 28 22:36:30 2022 -0700 @@ -27,6 +27,7 @@ * %*s length and string * * %p void * + * %P symbolized function address * %b njs_bool_t * %V njs_str_t * * %Z '\0' @@ -372,6 +373,11 @@ njs_vsprintf(u_char *buf, u_char *end, c */ goto number; + case 'P': + buf = njs_addr2line(buf, end, va_arg(args, void *)); + fmt++; + continue; + case 'c': d = va_arg(args, int); *buf++ = (u_char) (d & 0xFF); diff -r 20ee5213e3c4 -r 8fe7d9723477 src/njs_vmcode.c --- a/src/njs_vmcode.c Wed Jun 22 23:37:27 2022 -0700 +++ b/src/njs_vmcode.c Tue Jun 28 22:36:30 2022 -0700 @@ -165,8 +165,10 @@ next: * as a single unsigned comparision. */ -#ifdef NJS_OPCODE_DEBUG - njs_disassemble(pc, NULL, 1, NULL); +#ifdef NJS_DEBUG_OPCODE + if (vm->options.opcode_debug) { + njs_disassemble(pc, NULL, 1, NULL); + } #endif if (op > NJS_VMCODE_NORET) { diff -r 20ee5213e3c4 -r 8fe7d9723477 src/njs_vmcode.h --- a/src/njs_vmcode.h Wed Jun 22 23:37:27 2022 -0700 +++ b/src/njs_vmcode.h Tue Jun 28 22:36:30 2022 -0700 @@ -450,9 +450,9 @@ njs_int_t njs_vmcode_interpreter(njs_vm_ njs_object_t *njs_function_new_object(njs_vm_t *vm, njs_value_t *constructor); -#ifdef NJS_OPCODE_DEBUG +#ifdef NJS_DEBUG_OPCODE #define njs_vmcode_debug(vm, pc, prefix) { \ - do { \ + if (vm->options.opcode_debug) do { \ njs_vm_code_t *code; \ \ code = njs_lookup_code(vm, pc); \ diff -r 20ee5213e3c4 -r 8fe7d9723477 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Wed Jun 22 23:37:27 2022 -0700 +++ b/src/test/njs_unit_test.c Tue Jun 28 22:36:30 2022 -0700 @@ -13269,7 +13269,7 @@ static njs_unit_test_t njs_test[] = njs_str("5") }, { njs_str("var a = (new Function('return [' + ','.repeat(2**16) + ']'))();" - "njs.dump(a)"), + "njs.dump(a)"), njs_str("[<65536 empty items>]") }, { njs_str("(new Function('var a = 7; return a' + '= a'.repeat(2**13)))()"), @@ -23415,6 +23415,43 @@ njs_to_int32_test(njs_vm_t *vm, njs_opts } +#ifdef NJS_HAVE_ADDR2LINE +static njs_int_t +njs_addr2line_test(njs_vm_t *vm, njs_opts_t *opts, njs_stat_t *stat) +{ + njs_str_t v; + njs_uint_t i; + u_char buf[512]; + + static const struct { + void *fp; + const char *name; + } tests[] = { + { njs_addr2line_test, njs_stringify(njs_addr2line_test) }, + { njs_to_int32_test, njs_stringify(njs_to_int32_test) }, + }; + + for (i = 0; i < njs_nitems(tests); i++) { + v.start = buf; + v.length = njs_sprintf(buf, &buf[512], "%P", tests[i].fp) - buf; + + if (memcmp(buf, tests[i].name, njs_strlen(tests[i].name))) { + njs_printf("njs_addr2line_test(%p):\n" + "expected: %s\n got: %V\n", + tests[i].fp, tests[i].name, &v); + + stat->failed++; + continue; + } + + stat->passed++; + } + + return NJS_OK; +} +#endif + + static njs_int_t njs_vm_internal_api_test(njs_unit_test_t unused[], size_t num, njs_str_t *name, njs_opts_t *opts, njs_stat_t *stat) @@ -23443,6 +23480,10 @@ njs_vm_internal_api_test(njs_unit_test_t njs_str("njs_string_to_index_test") }, { njs_to_int32_test, njs_str("njs_to_int32_test") }, +#ifdef NJS_HAVE_ADDR2LINE + { njs_addr2line_test, + njs_str("njs_addr2line_test") }, +#endif }; vm = NULL; _______________________________________________ nginx-devel mailing list -- nginx-devel@nginx.org To unsubscribe send an email to nginx-devel-le...@nginx.org