diff options
39 files changed, 778 insertions, 157 deletions
diff --git a/COPYING.MDSO b/COPYING.MDSO index a1b6f65..65070ed 100644 --- a/COPYING.MDSO +++ b/COPYING.MDSO @@ -2,7 +2,7 @@ /* */ /* mdso: midipix dso scavenger */ /* */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* */ /* 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 */ diff --git a/COPYING.SOFORT b/COPYING.SOFORT index 5e75bb6..1c8a6c1 100644 --- a/COPYING.SOFORT +++ b/COPYING.SOFORT @@ -2,7 +2,7 @@ /* */ /* sofort: portable software project skeleton */ /* */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* */ /* sofort provides a build system that can be incorporated into Works */ /* which may or may not be covered by a copyleft license. THE FOLLOWING */ diff --git a/Makefile.in b/Makefile.in index 4e0f9e9..5ad6ff0 100644 --- a/Makefile.in +++ b/Makefile.in @@ -84,7 +84,6 @@ CFLAGS_DEBUG += @cflags_debug@ CFLAGS_CMDLINE += @cflags_cmdline@ CFLAGS_CONFIG += @cflags_config@ CFLAGS_SYSROOT += @cflags_sysroot@ -CFLAGS_OS += @cflags_os@ CFLAGS_SITE += @cflags_site@ CFLAGS_PATH += @cflags_path@ CFLAGS_STRICT += @cflags_strict@ diff --git a/config.usage b/config.usage index 33d1e58..41fe629 100644 --- a/config.usage +++ b/config.usage @@ -143,7 +143,7 @@ supported variables: TOOLCHAIN SYSROOT CROSS_COMPILE - SHELL + CONFIG_SHELL PKGCONF PKGCONFIG @@ -33,7 +33,12 @@ usage() " ___________________________________________" \ "__________________________________" - cat "$mb_project_dir"/project/config/cfgdefs.usage + if [ -f "$mb_project_dir"/project/config/cfgdefs.usage ]; then + cat "$mb_project_dir"/project/config/cfgdefs.usage + else + printf '%s\n\n' \ + "[ info: this project does not provide a project-specific cfgdefs.usage file. ]" + fi fi exit 0 @@ -275,7 +280,7 @@ init_vars() mb_toolchain=$TOOLCHAIN mb_sysroot=$SYSROOT mb_cross_compile=$CROSS_COMPILE - mb_shell=$SHELL + mb_shell=$CONFIG_SHELL # pkgconf mb_pkgconf=$PKGCONF @@ -713,7 +718,7 @@ config_flags() # ccstrict if [ _$mb_ccstrict = _yes ]; then - mb_cflags_strict='$(_CFLAGS_Wall) $(_CFLAGS_Werror) $(_CFLAGS_Wextra) $(_CFLAGS_Wundef)' + mb_cflags_strict='$(_CFLAGS_Wall) $(_CFLAGS_Werror) $(_CFLAGS_Wextra) $(_CFLAGS_Wundef) $(_CFLAGS_Wpedantic)' fi # ldstrict @@ -842,26 +847,9 @@ config_ccenv() error_msg "${mb_pretty} forcing native mode when cross-building is strictly prohibited." fi - # add the include and library directories to the compiler and linker search path - if [ "$mb_cchost" = "$mb_native_cchost" ]; then - mb_cflags_last="$mb_cflags_last -I$mb_includedir" - mb_ldflags_last="$mb_ldflags_last -L$mb_libdir" - else - case "$mb_libdir" in - /*) - mb_cflags_last="$mb_cflags_last -I$mb_sysroot/.$mb_includedir" - mb_ldflags_last="$mb_ldflags_last -L$mb_sysroot/.$mb_libdir" - ;; - *) - mb_cflags_last="$mb_cflags_last -I$mb_includedir" - mb_ldflags_last="$mb_ldflags_last -L$mb_libdir" - esac - fi - # re-generate Makefile.tmp output_section_break config_copy - } config_custom_cfgdefs() @@ -944,7 +932,7 @@ config_host() mb_cfghost_cflags="$mb_cfghost_cflags -ffreestanding" mb_cfghost_cflags="$mb_cfghost_cflags -nostdlib" else - printf 'int main(void){return 0;}' \ + printf 'int main(void){return 0;}\n' \ > "$mb_cfghost_tmpname" fi @@ -1123,6 +1111,9 @@ for arg ; do --mandir=*) mb_mandir=${arg#*=} ;; + --docdir=*) + mb_docdir=${arg#*=} + ;; --libexecdir=*) mb_libexecdir=${arg#*=} ;; diff --git a/project/common.mk b/project/common.mk index a52f593..95f765d 100644 --- a/project/common.mk +++ b/project/common.mk @@ -22,6 +22,7 @@ API_SRCS = \ INTERNAL_SRCS = \ src/internal/$(PACKAGE)_dprintf_impl.c \ src/internal/$(PACKAGE)_errinfo_impl.c \ + src/internal/$(PACKAGE)_hexfmt_impl.c \ APP_SRCS = \ src/mdso.c diff --git a/project/headers.mk b/project/headers.mk index a238cfe..d4a351a 100644 --- a/project/headers.mk +++ b/project/headers.mk @@ -14,6 +14,7 @@ INTERNAL_HEADERS = \ $(PROJECT_DIR)/src/internal/$(PACKAGE)_dprintf_impl.h \ $(PROJECT_DIR)/src/internal/$(PACKAGE)_driver_impl.h \ $(PROJECT_DIR)/src/internal/$(PACKAGE)_errinfo_impl.h \ + $(PROJECT_DIR)/src/internal/$(PACKAGE)_hexfmt_impl.h \ $(PROJECT_DIR)/src/internal/$(PACKAGE)_object_impl.h \ ALL_HEADERS = $(API_HEADERS) $(INTERNAL_HEADERS) diff --git a/sofort/ccenv/ccenv.in b/sofort/ccenv/ccenv.in index 441f8ab..0daff84 100644 --- a/sofort/ccenv/ccenv.in +++ b/sofort/ccenv/ccenv.in @@ -84,8 +84,13 @@ PKGCONF = @ccenv_pkgconf@ AS = @ccenv_as@ LD = @ccenv_ld@ +# @ccenv_cfgtype@ visibility attributes +CFLAGS_ATTR_VISIBILITY_DEFAULT = -D_ATTR_VISIBILITY_DEFAULT=@ccenv_attr_visibility_default@ +CFLAGS_ATTR_VISIBILITY_HIDDEN = -D_ATTR_VISIBILITY_HIDDEN=@ccenv_attr_visibility_hidden@ +CFLAGS_ATTR_VISIBILITY_INTERNAL = -D_ATTR_VISIBILITY_INTERNAL=@ccenv_attr_visibility_internal@ +CFLAGS_ATTR_VISIBILITY_PROTECTED = -D_ATTR_VISIBILITY_PROTECTED=@ccenv_attr_visibility_protected@ + # @ccenv_cfgtype@ cflags CFLAGS_OS += -DOS_LIB_SUFFIX=\"@ccenv_os_lib_suffix@\" CFLAGS_OS += @ccenv_cflags_os@ CFLAGS_PIC += @ccenv_cflags_pic@ - diff --git a/sofort/ccenv/ccenv.sh b/sofort/ccenv/ccenv.sh index a13aa07..d975c6b 100644 --- a/sofort/ccenv/ccenv.sh +++ b/sofort/ccenv/ccenv.sh @@ -1118,14 +1118,20 @@ ccenv_set_os() fi case "$ccenv_cchost" in - *-*-*-* ) - ccenv_tip=${ccenv_cchost%-*} - ccenv_os=${ccenv_tip#*-*-} - ;; *-*-musl | *-*-gnu ) ccenv_tip=${ccenv_cchost%-*} ccenv_os=${ccenv_tip#*-} ;; + *-*-solaris* ) + ccenv_os='solaris' + ;; + *-*-*bsd* | *-*-dragonfly* ) + ccenv_os='bsd' + ;; + *-*-*-* ) + ccenv_tip=${ccenv_cchost%-*} + ccenv_os=${ccenv_tip#*-*-} + ;; *-*-* ) ccenv_os=${ccenv_cchost#*-*-} ;; @@ -1412,6 +1418,42 @@ ccenv_set_os_pe_switches() ;; esac fi + + if [ "$ccenv_cc_binfmt" = 'PE' ]; then + if ! cfgtest_macro_definition '__PE__'; then + ccenv_cflags_os="${ccenv_cflags_os} -D__PE__" + fi + + if ! cfgtest_macro_definition '__dllexport'; then + ccenv_cflags_os="${ccenv_cflags_os} -D__dllexport=__attribute__\(\(__dllexport__\)\)" + fi + + if ! cfgtest_macro_definition '__dllimport'; then + ccenv_cflags_os="${ccenv_cflags_os} -D__dllimport=__attribute__\(\(__dllimport__\)\)" + fi + fi +} + +ccenv_set_os_gate_switches() +{ + if [ "$ccenv_os" = 'solaris' ]; then + if ! cfgtest_macro_definition 'AT_FDCWD'; then + ccenv_cflags_os="${ccenv_cflags_os} -D__EXTENSIONS__" + fi + fi +} + +ccenv_set_os_bsd_switches() +{ + if [ "$ccenv_os" = 'bsd' ]; then + mb_cfgtest_headers='sys/mman.h' + + if ! cfgtest_macro_definition 'MAP_ANON'; then + ccenv_cflags_os="${ccenv_cflags_os} -D__BSD_VISIBLE" + fi + + mb_cfgtest_headers= + fi } ccenv_output_defs() @@ -1654,6 +1696,25 @@ ccenv_set_cc_linker_switch_vars() done } +ccenv_set_cc_attr_visibility_vars() +{ + if cfgtest_attr_visibility 'default'; then + ccenv_attr_visibility_default="$mb_cfgtest_attr" + fi + + if cfgtest_attr_visibility 'hidden'; then + ccenv_attr_visibility_hidden="$mb_cfgtest_attr" + fi + + if cfgtest_attr_visibility 'internal'; then + ccenv_attr_visibility_internal="$mb_cfgtest_attr" + fi + + if cfgtest_attr_visibility 'protected'; then + ccenv_attr_visibility_protected="$mb_cfgtest_attr" + fi +} + ccenv_dso_verify() { ccenv_str='int foo(int x){return ++x;}' @@ -1760,6 +1821,9 @@ ccenv_set_toolchain_variables() ccenv_set_os_dso_linkage ccenv_set_os_dso_patterns ccenv_set_os_pe_switches + ccenv_set_os_gate_switches + ccenv_set_os_bsd_switches + ccenv_set_cc_attr_visibility_vars ccenv_output_defs ccenv_clean_up diff --git a/sofort/ccenv/ccenv.vars b/sofort/ccenv/ccenv.vars index 41eb327..054b638 100644 --- a/sofort/ccenv/ccenv.vars +++ b/sofort/ccenv/ccenv.vars @@ -82,6 +82,12 @@ ccenv_windrc= ccenv_pkgconf= +# visibility attributes +ccenv_attr_visibility_default= +ccenv_attr_visibility_hidden= +ccenv_attr_visibility_internal= +ccenv_attr_visibility_protected= + # cflags ccenv_cflags_os= ccenv_cflags_pic= diff --git a/sofort/ccenv/ccswitch.strs b/sofort/ccenv/ccswitch.strs index 0a76f03..277e02e 100644 --- a/sofort/ccenv/ccswitch.strs +++ b/sofort/ccenv/ccswitch.strs @@ -34,6 +34,7 @@ -Werror -Wextra -Wundef +-Wpedantic # debugging -g diff --git a/sofort/cfgtest/cfgtest.sh b/sofort/cfgtest/cfgtest.sh index debdb8c..7bb27a0 100644 --- a/sofort/cfgtest/cfgtest.sh +++ b/sofort/cfgtest/cfgtest.sh @@ -15,6 +15,7 @@ # mb_cfgtest_cfgtype: the type of the current test (host/native) # mb_cfgtest_makevar: the make variable affected by the current test # mb_cfgtest_headers: headers for ad-hoc inclusion with the current test +# mb_cfgtest_attr: if supported, the compiler-specific attribute definition cfgtest_newline() @@ -131,6 +132,15 @@ cfgtest_epilog() return 1 fi + if [ "${1}" = 'attr' ] && [ "${2}" = '(error)' ]; then + printf '\n\ncfgtest: the %s compiler %s %s_ attribute.\n' \ + "$mb_cfgtest_cfgtype" \ + 'does not appear to support the _' \ + "${3}" >&3 + printf '%s\n' '------------------------' >&3 + return 1 + fi + if [ "${2}" = '-----' ] || [ "${2}" = '(missing)' ]; then printf '\n\ncfgtest: %s %s is missing or cannot be found.\n' "${1}" "${3}" >&3 printf '%s\n' '------------------------' >&3 @@ -246,6 +256,8 @@ cfgtest_common_init() fi elif [ "$cfgtest_type" = 'asm' ]; then cfgtest_fmt='%s -c -xc - -o a.out' + elif [ "$cfgtest_type" = 'attr' ]; then + cfgtest_fmt='%s -c -xc - -o a.out -Werror' elif [ "$cfgtest_type" = 'lib' ]; then cfgtest_fmt='%s -xc - -o a.out' elif [ "$cfgtest_type" = 'ldflag' ]; then @@ -330,11 +342,16 @@ cfgtest_header_presence() cfgtest_prolog 'header' "${1}" cfgtest_code_snippet=$(printf '#include <%s>\n' "${1}") + cfgtest_code_onedecl='int fn(void){return 0;}' + + cfgtest_code_snippet=$(printf '%s\n%s\n' \ + "$cfgtest_code_snippet" \ + "$cfgtest_code_onedecl") cfgtest_common_init # execute - printf '%s' "$cfgtest_src" \ + printf '%s\n' "$cfgtest_src" \ | eval $(printf '%s' "$cfgtest_cmd") \ > /dev/null 2>&3 \ || cfgtest_epilog 'header' '-----' "<${1}>" \ @@ -365,11 +382,16 @@ cfgtest_header_absence() cfgtest_prolog 'header absence' "${1}" cfgtest_code_snippet=$(printf '#include <%s>\n' "${1}") + cfgtest_code_onedecl='int fn(void){return 0;}' + + cfgtest_code_snippet=$(printf '%s\n%s\n' \ + "$cfgtest_code_snippet" \ + "$cfgtest_code_onedecl") cfgtest_common_init # execute - printf '%s' "$cfgtest_src" \ + printf '%s\n' "$cfgtest_src" \ | eval $(printf '%s' "$cfgtest_cmd") \ > /dev/null 2>&3 \ && printf 'cfgtest: %s header <%s>: no error.' \ @@ -401,12 +423,12 @@ cfgtest_interface_presence() # init cfgtest_prolog 'interface' "${1}" - cfgtest_code_snippet=$(printf 'void * addr = &%s;\n' "${1}") + cfgtest_code_snippet=$(printf 'void (*addr)() = (void (*)())&%s;\n' "${1}") cfgtest_common_init # execute - printf '%s' "$cfgtest_src" \ + printf '%s\n' "$cfgtest_src" \ | eval $(printf '%s' "$cfgtest_cmd") \ > /dev/null 2>&3 \ || cfgtest_epilog 'interface' '(error)' "${1}" \ @@ -443,7 +465,7 @@ cfgtest_decl_presence() cfgtest_common_init # execute - printf '%s' "$cfgtest_src" \ + printf '%s\n' "$cfgtest_src" \ | eval $(printf '%s' "$cfgtest_cmd") \ > /dev/null 2>&3 \ || cfgtest_epilog 'decl' '(error)' "${1}" \ @@ -496,7 +518,7 @@ cfgtest_type_size() cfgtest_common_init - printf '%s' "$cfgtest_src" \ + printf '%s\n' "$cfgtest_src" \ | eval $(printf '%s' "$cfgtest_cmd") \ > /dev/null 2>&3 \ && mb_internal_size=$mb_internal_guess @@ -534,6 +556,39 @@ cfgtest_type_size() } +cfgtest_attr_visibility() +{ + # init + cfgtest_prolog 'compiler visibility attr' "${1}" + + cfgtest_attr_syntax='__attribute__((__visibility__("'"${1}"'")))' + cfgtest_code_snippet="$cfgtest_attr_syntax"' int f_'"${1}"'(void);' + + cfgtest_common_init 'attr' + + # execute + cfgtest_ret=1 + + printf '%s\n' "$cfgtest_src" \ + | eval $(printf '%s' "$cfgtest_cmd") \ + > /dev/null 2>&3 \ + || cfgtest_epilog 'attr' '(error)' "${1}" \ + || return + + # result + mb_cfgtest_attr=$(printf '__attribute__\\(\\(__visibility__\\(\\"%s\\"\\)\\)\\)' "${1}") + + cfgtest_ret=0 + + printf 'cfgtest: %s compiler: above attribute is supported; see also ccenv/%s.mk.\n\n' \ + "$mb_cfgtest_cfgtype" "$mb_cfgtest_cfgtype" >&3 + + cfgtest_epilog 'attr' '(ok)' + + return 0 +} + + cfgtest_code_snippet_asm() { # init @@ -546,7 +601,7 @@ cfgtest_code_snippet_asm() # execute cfgtest_ret=1 - printf '%s' "$cfgtest_src" \ + printf '%s\n' "$cfgtest_src" \ | eval $(printf '%s' "$cfgtest_cmd") \ > /dev/null 2>&3 \ || cfgtest_epilog 'snippet' '(error)' \ @@ -579,7 +634,7 @@ cfgtest_macro_definition() # execute cfgtest_ret=1 - printf '%s' "$cfgtest_src" \ + printf '%s\n' "$cfgtest_src" \ | eval $(printf '%s' "$cfgtest_cmd") \ > /dev/null 2>&3 \ || cfgtest_epilog 'macro' '(error)' "${1}" \ @@ -627,7 +682,7 @@ cfgtest_library_presence() cfgtest_common_init 'lib' # execute - printf '%s' "$cfgtest_src" \ + printf '%s\n' "$cfgtest_src" \ | eval $(printf '%s' "$cfgtest_cmd") \ > /dev/null 2>&3 \ || cfgtest_epilog 'library' '-----' "$@" \ @@ -805,20 +860,20 @@ cfgtest_compiler_switch() ;; *) - cfgtest_code_snippet= + cfgtest_code_snippet='int fn(void){return 0;}' cfgtest_common_init 'switch' ;; esac # execute - printf '%s' "$cfgtest_src" \ + printf '%s\n' "$cfgtest_src" \ | eval $(printf '%s' "$cfgtest_cmd") \ > /dev/null 2>&3 \ || cfgtest_epilog 'switch' '(error)' "$@" \ || return 1 # result - printf 'cfgtest: the switch `%s was accepted by the compier.\n' \ + printf 'cfgtest: the switch `%s was accepted by the compiler.\n' \ "$cfgtest_switches'" >&3 printf '%s\n' '------------------------' >&3 diff --git a/sofort/config/config.vars b/sofort/config/config.vars index 0c01a29..38d5616 100644 --- a/sofort/config/config.vars +++ b/sofort/config/config.vars @@ -54,6 +54,7 @@ zealous sysroot freestanding cross_compile +config_shell shell pkgconf diff --git a/src/archive/mdso_argen_common.c b/src/archive/mdso_argen_common.c index 2523efd..2d2f3c5 100644 --- a/src/archive/mdso_argen_common.c +++ b/src/archive/mdso_argen_common.c @@ -1,6 +1,6 @@ /****************************************************************/ /* mdso: midipix dso scavenger */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ /****************************************************************/ @@ -11,16 +11,31 @@ #include <sys/mman.h> #include <mdso/mdso.h> +#include "mdso_object_impl.h" #include "mdso_errinfo_impl.h" #include "perk_structs.h" +static void mdso_obj_write_objname(char * ch, off_t objidx) +{ + ch[0] = 's'; + + ch[6] = (objidx % 10) + '0'; objidx /= 10; + ch[5] = (objidx % 10) + '0'; objidx /= 10; + ch[4] = (objidx % 10) + '0'; objidx /= 10; + ch[3] = (objidx % 10) + '0'; objidx /= 10; + ch[2] = (objidx % 10) + '0'; objidx /= 10; + ch[1] = (objidx % 10) + '0'; objidx /= 10; + + ch[7] = '.'; + ch[8] = 'o'; +} + static void mdso_argen_common_hdr( struct pe_raw_archive_common_hdr * arhdr, char * file_id, size_t size) { size_t slen; - char sbuf[10]; memset(arhdr,0x20,sizeof(*arhdr)); @@ -33,8 +48,7 @@ static void mdso_argen_common_hdr( arhdr->ar_file_mode[0] = '0'; arhdr->ar_time_date_stamp[0] = '0'; - slen = sprintf(sbuf,"%zu",size); - memcpy(arhdr->ar_file_size,sbuf,slen); + mdso_obj_write_dec(arhdr->ar_file_size,size); arhdr->ar_end_tag[0] = 0x60; arhdr->ar_end_tag[1] = 0x0a; @@ -138,10 +152,6 @@ int mdso_argen_common( objlen += sizeof(uint32_t) * (1 + mapstrsnum); objlen += mapstrslen; - objlen += 15; - objlen |= 15; - objlen ^= 15; - /* archive meta info, in-memory mapping */ if (vobj->addr && (vobj->size < objlen)) return MDSO_BUFFER_ERROR(dctx); @@ -216,9 +226,7 @@ int mdso_argen_common( idx += sizeof(uint32_t); } - sprintf( - objname,"s%06zu.o", - psym - symv); + mdso_obj_write_objname(objname,psym - symv); ret = mdso_objgen_symentry(dctx,*psym,pobj); diff --git a/src/crc/mdso_crc32.c b/src/crc/mdso_crc32.c index 15f60fb..85c90d4 100644 --- a/src/crc/mdso_crc32.c +++ b/src/crc/mdso_crc32.c @@ -1,6 +1,6 @@ /****************************************************************/ /* mdso: midipix dso scavenger */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ /****************************************************************/ diff --git a/src/crc/mdso_crc64.c b/src/crc/mdso_crc64.c index 6c599cc..8745396 100644 --- a/src/crc/mdso_crc64.c +++ b/src/crc/mdso_crc64.c @@ -1,6 +1,6 @@ /****************************************************************/ /* mdso: midipix dso scavenger */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ /****************************************************************/ diff --git a/src/driver/mdso_amain.c b/src/driver/mdso_amain.c index 4b2ba34..25c1f7c 100644 --- a/src/driver/mdso_amain.c +++ b/src/driver/mdso_amain.c @@ -1,6 +1,6 @@ /****************************************************************/ /* mdso: midipix dso scavenger */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ /****************************************************************/ diff --git a/src/driver/mdso_driver_ctx.c b/src/driver/mdso_driver_ctx.c index 0f4ea56..bfa0d9e 100644 --- a/src/driver/mdso_driver_ctx.c +++ b/src/driver/mdso_driver_ctx.c @@ -1,6 +1,6 @@ /****************************************************************/ /* mdso: midipix dso scavenger */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ /****************************************************************/ diff --git a/src/driver/mdso_unit_ctx.c b/src/driver/mdso_unit_ctx.c index fdbfbd6..f21ccc4 100644 --- a/src/driver/mdso_unit_ctx.c +++ b/src/driver/mdso_unit_ctx.c @@ -1,6 +1,6 @@ /****************************************************************/ /* mdso: midipix dso scavenger */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ /****************************************************************/ diff --git a/src/helper/mdso_create_output.c b/src/helper/mdso_create_output.c index bb1cfe9..163c5a5 100644 --- a/src/helper/mdso_create_output.c +++ b/src/helper/mdso_create_output.c @@ -1,6 +1,6 @@ /****************************************************************/ /* mdso: midipix dso scavenger */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ /****************************************************************/ diff --git a/src/helper/mdso_map_input.c b/src/helper/mdso_map_input.c index c899b42..df8072f 100644 --- a/src/helper/mdso_map_input.c +++ b/src/helper/mdso_map_input.c @@ -1,6 +1,6 @@ /****************************************************************/ /* mdso: midipix dso scavenger */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ /****************************************************************/ diff --git a/src/internal/argv/argv.h b/src/internal/argv/argv.h index 973983a..66f80b4 100644 --- a/src/internal/argv/argv.h +++ b/src/internal/argv/argv.h @@ -1,6 +1,6 @@ /****************************************************************************/ /* argv.h: a thread-safe argument vector parser and usage screen generator */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ /****************************************************************************/ @@ -13,6 +13,7 @@ #include <string.h> #include <stdlib.h> #include <stdio.h> +#include <ctype.h> #include <unistd.h> #define ARGV_VERBOSITY_NONE 0x00 @@ -57,16 +58,27 @@ #define ARGV_OPTION_HYBRID_EQUAL 0x04 #define ARGV_OPTION_HYBRID_COMMA 0x08 #define ARGV_OPTION_HYBRID_JOINED 0x10 + +#define ARGV_OPTION_KEYVAL_PAIR 0X20 +#define ARGV_OPTION_KEYVAL_ARRAY 0X40 +#define ARGV_OPTION_KEYVAL_MASK (ARGV_OPTION_KEYVAL_PAIR \ + | ARGV_OPTION_KEYVAL_ARRAY) + #define ARGV_OPTION_HYBRID_CIRCUS (ARGV_OPTION_HYBRID_SPACE \ | ARGV_OPTION_HYBRID_JOINED) + #define ARGV_OPTION_HYBRID_DUAL (ARGV_OPTION_HYBRID_SPACE \ | ARGV_OPTION_HYBRID_EQUAL) + #define ARGV_OPTION_HYBRID_SWITCH (ARGV_OPTION_HYBRID_ONLY \ | ARGV_OPTION_HYBRID_SPACE \ | ARGV_OPTION_HYBRID_EQUAL \ | ARGV_OPTION_HYBRID_COMMA \ | ARGV_OPTION_HYBRID_JOINED) +#define ARGV_KEYVAL_ASSIGN 0x01 +#define ARGV_KEYVAL_OVERRIDE 0x02 + enum argv_optarg { ARGV_OPTARG_NONE, ARGV_OPTARG_REQUIRED, @@ -83,6 +95,7 @@ enum argv_error { ARGV_ERROR_INTERNAL, ARGV_ERROR_SHORT_OPTION, ARGV_ERROR_LONG_OPTION, + ARGV_ERROR_VENDOR_OPTION, ARGV_ERROR_OPTARG_NONE, ARGV_ERROR_OPTARG_REQUIRED, ARGV_ERROR_OPTARG_PARADIGM, @@ -91,6 +104,9 @@ enum argv_error { ARGV_ERROR_HYBRID_SPACE, ARGV_ERROR_HYBRID_EQUAL, ARGV_ERROR_HYBRID_COMMA, + ARGV_ERROR_KEYVAL_KEY, + ARGV_ERROR_KEYVAL_VALUE, + ARGV_ERROR_KEYVAL_ALLOC, }; struct argv_option { @@ -104,13 +120,20 @@ struct argv_option { const char * description; }; +struct argv_keyval { + const char * keyword; + const char * value; + int flags; +}; + struct argv_entry { - const char * arg; - int tag; - bool fopt; - bool fval; - bool fnoscan; - enum argv_error errcode; + const char * arg; + struct argv_keyval * keyv; + int tag; + bool fopt; + bool fval; + bool fnoscan; + enum argv_error errcode; }; struct argv_meta { @@ -128,6 +151,7 @@ struct argv_ctx { const char * errch; const struct argv_option * erropt; const char * program; + size_t keyvlen; }; #ifdef ARGV_DRIVER @@ -135,6 +159,8 @@ struct argv_ctx { struct argv_meta_impl { char ** argv; char * strbuf; + char * keyvbuf; + char * keyvmark; struct argv_meta meta; }; @@ -304,12 +330,131 @@ static inline const struct argv_option * option_from_tag( return 0; } +static inline int argv_scan_keyval_array(struct argv_meta_impl * meta, struct argv_entry * entry) +{ + const char * ch; + char * dst; + int ncomma; + int cint; + struct argv_keyval * keyv; + + /* count key[val] elements, assume no comma after last element */ + for (ch=entry->arg,ncomma=1; *ch; ch++) { + if ((ch[0]=='\\') && (ch[1]==',')) { + ch++; + + } else if ((ch[0]==',')) { + ncomma++; + } + } + + /* keyval string buffer */ + dst = meta->keyvmark; + + /* allocate keyval array */ + if (!(entry->keyv = calloc(ncomma+1,sizeof(*entry->keyv)))) + return ARGV_ERROR_KEYVAL_ALLOC; + + /* create keyval array */ + entry->keyv->keyword = dst; + + for (ch=entry->arg,keyv=entry->keyv; *ch; ch++) { + if ((ch[0]=='\\') && (ch[1]==',')) { + *dst++ = ','; + ch++; + + } else if ((ch[0]==':') && (ch[1]=='=')) { + if (!keyv->keyword[0]) + return ARGV_ERROR_KEYVAL_KEY; + + keyv->flags = ARGV_KEYVAL_OVERRIDE; + keyv->value = ++dst; + ch++; + + } else if ((ch[0]=='=')) { + if (!keyv->keyword[0]) + return ARGV_ERROR_KEYVAL_KEY; + + keyv->flags = ARGV_KEYVAL_ASSIGN; + keyv->value = ++dst; + + } else if ((ch[0]==',')) { + for (; isblank(cint = ch[1]); ) + ch++; + + if (ch[1]) { + keyv++; + keyv->keyword = ++dst; + } + } else { + *dst++ = *ch; + } + } + + /* keyval string buffer */ + meta->keyvmark = ++dst; + + return ARGV_ERROR_OK; +} + +static inline int argv_scan_keyval_pair(struct argv_meta_impl * meta, struct argv_entry * entry) +{ + const char * ch; + char * dst; + struct argv_keyval * keyv; + + /* keyval string buffer */ + dst = meta->keyvmark; + + /* allocate keyval array */ + if (!(entry->keyv = calloc(2,sizeof(*entry->keyv)))) + return ARGV_ERROR_KEYVAL_ALLOC; + + /* create keyval array */ + entry->keyv->keyword = dst; + + for (ch=entry->arg,keyv=entry->keyv; *ch && !keyv->flags; ch++) { + if ((ch[0]=='\\') && (ch[1]==',')) { + *dst++ = ','; + ch++; + + } else if ((ch[0]==':') && (ch[1]=='=')) { + if (!keyv->keyword[0]) + return ARGV_ERROR_KEYVAL_KEY; + + keyv->flags = ARGV_KEYVAL_OVERRIDE; + keyv->value = ++dst; + ch++; + + } else if ((ch[0]=='=')) { + if (!keyv->keyword[0]) + return ARGV_ERROR_KEYVAL_KEY; + + keyv->flags = ARGV_KEYVAL_ASSIGN; + keyv->value = ++dst; + + } else { + *dst++ = *ch; + } + } + + for (; *ch; ) + *dst++ = *ch++; + + /* keyval string buffer */ + meta->keyvmark = ++dst; + + return ARGV_ERROR_OK; +} + static void argv_scan( char ** argv, const struct argv_option ** optv, struct argv_ctx * ctx, struct argv_meta * meta) { + struct argv_meta_impl * imeta; + uintptr_t addr; char ** parg; const char * ch; const char * val; @@ -323,6 +468,9 @@ static void argv_scan( bool fhybrid; bool fnoscan; + addr = (uintptr_t)meta - offsetof(struct argv_meta_impl,meta); + imeta = (struct argv_meta_impl *)addr; + parg = &argv[1]; ch = *parg; ferr = ARGV_ERROR_OK; @@ -398,7 +546,11 @@ static void argv_scan( fval = ch; } } else { - ferr = ARGV_ERROR_SHORT_OPTION; + if ((ch == &parg[0][1]) && (ch[0] == 'W') && ch[1]) { + ferr = ARGV_ERROR_VENDOR_OPTION; + } else { + ferr = ARGV_ERROR_SHORT_OPTION; + } } } else if (!fnoscan && (fhybrid || is_long_option(ch))) { @@ -413,49 +565,72 @@ static void argv_scan( ch = *parg; } - if (fhybrid && !(option->flags & ARGV_OPTION_HYBRID_SWITCH)) + /* now verify the proper setting of option values */ + if (fhybrid && !(option->flags & ARGV_OPTION_HYBRID_SWITCH)) { ferr = ARGV_ERROR_HYBRID_NONE; - else if (!fhybrid && (option->flags & ARGV_OPTION_HYBRID_ONLY)) + + } else if (!fhybrid && (option->flags & ARGV_OPTION_HYBRID_ONLY)) { ferr = ARGV_ERROR_HYBRID_ONLY; - else if (option->optarg == ARGV_OPTARG_NONE) { + + } else if (option->optarg == ARGV_OPTARG_NONE) { if (val[0]) { ferr = ARGV_ERROR_OPTARG_NONE; ctx->errch = val + 1; - } else + } else { fval = false; + } + } else if (val[0] && (option->flags & ARGV_OPTION_HYBRID_JOINED)) { fval = true; ch = val; - } else if (fhybrid && !val[0] && !(option->flags & ARGV_OPTION_HYBRID_SPACE)) - ferr = ARGV_ERROR_HYBRID_SPACE; - else if (fhybrid && (val[0]=='=') && !(option->flags & ARGV_OPTION_HYBRID_EQUAL)) + + } else if (fhybrid && !val[0] && !(option->flags & ARGV_OPTION_HYBRID_SPACE)) { + if (option->optarg == ARGV_OPTARG_OPTIONAL) { + fval = false; + + } else { + ferr = ARGV_ERROR_HYBRID_SPACE; + } + + } else if (fhybrid && (val[0]=='=') && !(option->flags & ARGV_OPTION_HYBRID_EQUAL)) { ferr = ARGV_ERROR_HYBRID_EQUAL; - else if (fhybrid && (val[0]==',') && !(option->flags & ARGV_OPTION_HYBRID_COMMA)) + + } else if (fhybrid && (val[0]==',') && !(option->flags & ARGV_OPTION_HYBRID_COMMA)) { ferr = ARGV_ERROR_HYBRID_COMMA; - else if (!fhybrid && (val[0]==',')) + + } else if (!fhybrid && (val[0]==',')) { ferr = ARGV_ERROR_HYBRID_COMMA; - else if (val[0] && !val[1]) + + } else if (val[0] && !val[1]) { ferr = ARGV_ERROR_OPTARG_REQUIRED; - else if (val[0] && val[1]) { + + } else if (val[0] && val[1]) { fval = true; ch = ++val; + } else if (option->optarg == ARGV_OPTARG_REQUIRED) { - if (!val[0] && !*parg) + if (!val[0] && !*parg) { ferr = ARGV_ERROR_OPTARG_REQUIRED; - else if (*parg && is_short_option(*parg)) + + } else if (*parg && is_short_option(*parg)) { ferr = ARGV_ERROR_OPTARG_REQUIRED; - else if (*parg && is_long_option(*parg)) + + } else if (*parg && is_long_option(*parg)) { ferr = ARGV_ERROR_OPTARG_REQUIRED; - else if (*parg && is_last_option(*parg)) + + } else if (*parg && is_last_option(*parg)) { ferr = ARGV_ERROR_OPTARG_REQUIRED; - else + + } else { fval = true; + } } else { /* ARGV_OPTARG_OPTIONAL */ fval = val[0]; } - } else + } else { ferr = ARGV_ERROR_LONG_OPTION; + } } if (ferr == ARGV_ERROR_OK) @@ -467,13 +642,20 @@ static void argv_scan( if (!option && !ctx->unitidx) ctx->unitidx = parg - argv; + if (ferr == ARGV_ERROR_OK) + if (option && (option->flags & ARGV_OPTION_KEYVAL_MASK)) + if (ctx->mode == ARGV_MODE_SCAN) + ctx->keyvlen += strlen(ch) + 1; + if (ferr != ARGV_ERROR_OK) { ctx->errcode = ferr; ctx->errch = ctx->errch ? ctx->errch : ch; ctx->erropt = option; ctx->erridx = parg - argv; return; - } else if (ctx->mode == ARGV_MODE_SCAN) { + } + + if (ctx->mode == ARGV_MODE_SCAN) { if (!fnoscan) ctx->nentries++; else if (fval) @@ -483,12 +665,12 @@ static void argv_scan( parg++; ch = *parg; } + } else if (ctx->mode == ARGV_MODE_COPY) { if (fnoscan) { if (fval) { mentry->arg = ch; mentry->fnoscan = true; - mentry++; } parg++; @@ -498,7 +680,6 @@ static void argv_scan( mentry->tag = option->tag; mentry->fopt = true; mentry->fval = fval; - mentry++; if (fval) { parg++; @@ -506,11 +687,28 @@ static void argv_scan( } } else { mentry->arg = ch; - mentry++; parg++; ch = *parg; } } + + if (option && (option->flags & ARGV_OPTION_KEYVAL_PAIR)) + if (ctx->mode == ARGV_MODE_COPY) + ferr = argv_scan_keyval_pair(imeta,mentry); + + if (option && (option->flags & ARGV_OPTION_KEYVAL_ARRAY)) + if (ctx->mode == ARGV_MODE_COPY) + ferr = argv_scan_keyval_array(imeta,mentry); + + if (ferr != ARGV_ERROR_OK) { + ctx->errcode = ferr; + ctx->errch = ctx->errch ? ctx->errch : ch; + ctx->erropt = option; + ctx->erridx = parg - argv; + return; + } + + mentry++; } } @@ -531,7 +729,11 @@ static const char * argv_program_name(const char * program_path) static void argv_show_error(int fd, struct argv_ctx * ctx) { - char opt_short_name[2] = {0,0}; + const char * src; + char * dst; + char * cap; + char opt_vendor_buf[256]; + char opt_short_name[2] = {0,0}; if (ctx->erropt && ctx->erropt->short_name) opt_short_name[0] = ctx->erropt->short_name; @@ -547,6 +749,27 @@ static void argv_show_error(int fd, struct argv_ctx * ctx) argv_dprintf(fd,"'--%s' is not a valid long option\n",ctx->errch); break; + case ARGV_ERROR_VENDOR_OPTION: + src = ctx->errch; + dst = opt_vendor_buf; + cap = &opt_vendor_buf[sizeof(opt_vendor_buf)]; + + for (; src && *src && dst<cap; ) { + if ((*src == '=') || (*src == ',') || (*src == ':')) { + src = 0; + } else { + *dst++ = *src++; + } + } + + if (dst == cap) + dst--; + + *dst = '\0'; + + argv_dprintf(fd,"'-%s' is not a valid vendor option\n",opt_vendor_buf); + break; + case ARGV_ERROR_OPTARG_NONE: argv_dprintf(fd,"'%s' is not a valid option value for [%s%s%s%s%s] " "(option values may not be specified)\n", @@ -610,6 +833,14 @@ static void argv_show_error(int fd, struct argv_ctx * ctx) break; + case ARGV_ERROR_KEYVAL_KEY: + argv_dprintf(fd,"illegal key detected in keyval argument\n"); + break; + + case ARGV_ERROR_KEYVAL_VALUE: + argv_dprintf(fd,"illegal value detected in keyval argument\n"); + break; + case ARGV_ERROR_INTERNAL: argv_dprintf(fd,"internal error"); break; @@ -625,8 +856,10 @@ static void argv_show_status( struct argv_ctx * ctx, struct argv_meta * meta) { + int i; int argc; char ** argv; + struct argv_keyval * keyv; struct argv_entry * entry; const struct argv_option * option; char short_name[2] = {0}; @@ -645,7 +878,7 @@ static void argv_show_status( argv_dprintf(fd,"argv[%d]: %s\n",argc,*argv); argv_dprintf(fd,"\n\nparsed entries:\n"); - for (entry=meta->entries; entry->arg || entry->fopt; entry++) + for (entry=meta->entries; entry->arg || entry->fopt; entry++) { if (entry->fopt) { option = option_from_tag(optv,entry->tag); short_name[0] = option->short_name; @@ -656,14 +889,48 @@ static void argv_show_status( else argv_dprintf(fd,"[-%s,--%s]\n", short_name,option->long_name); - } else + + if (entry->keyv) { + for (i=0,keyv=entry->keyv; keyv->keyword; i++,keyv++) { + switch (keyv->flags) { + case ARGV_KEYVAL_ASSIGN: + argv_dprintf(fd,"\tkeyval[%d]: <%s>=%s\n", + i,keyv->keyword,keyv->value); + break; + + case ARGV_KEYVAL_OVERRIDE: + argv_dprintf(fd,"\tkeyval[%d]: <%s>:=%s\n", + i,keyv->keyword,keyv->value); + break; + + default: + argv_dprintf(fd,"\tkeyval[%d]: <%s>\n", + i,keyv->keyword); + break; + } + } + } + } else { argv_dprintf(fd,"<program arg> := %s\n",entry->arg); + } + } argv_dprintf(fd,"\n\n"); } static struct argv_meta * argv_free_impl(struct argv_meta_impl * imeta) { + struct argv_entry * entry; + void * addr; + + if (imeta->keyvbuf) + for (entry=imeta->meta.entries; entry->fopt || entry->arg; entry++) + if (entry->keyv) + free((addr = entry->keyv)); + + if (imeta->keyvbuf) + free(imeta->keyvbuf); + if (imeta->argv) free(imeta->argv); @@ -697,7 +964,8 @@ static struct argv_meta * argv_alloc(char ** argv, struct argv_ctx * ctx) if (!(imeta->argv = calloc(argc+1,sizeof(char *)))) return argv_free_impl(imeta); - else if (!(imeta->strbuf = calloc(1,size+1))) + + if (!(imeta->strbuf = calloc(1,size+1))) return argv_free_impl(imeta); for (i=0,dst=imeta->strbuf; i<argc; i++) { @@ -707,15 +975,27 @@ static struct argv_meta * argv_alloc(char ** argv, struct argv_ctx * ctx) } imeta->meta.argv = imeta->argv; - } else + } else { imeta->meta.argv = argv; + } - if (!(imeta->meta.entries = calloc( - ctx->nentries+1, - sizeof(struct argv_entry)))) + imeta->meta.entries = calloc( + ctx->nentries+1, + sizeof(struct argv_entry)); + + if (!imeta->meta.entries) return argv_free_impl(imeta); - else - return &imeta->meta; + + if (ctx->keyvlen) { + imeta->keyvbuf = calloc( + ctx->keyvlen, + sizeof(char)); + + if (!(imeta->keyvmark = imeta->keyvbuf)) + return argv_free_impl(imeta); + } + + return &imeta->meta; } static struct argv_meta * argv_get( @@ -725,7 +1005,7 @@ static struct argv_meta * argv_get( int fd) { struct argv_meta * meta; - struct argv_ctx ctx = {flags,ARGV_MODE_SCAN,0,0,0,0,0,0,0}; + struct argv_ctx ctx = {flags,ARGV_MODE_SCAN,0,0,0,0,0,0,0,0}; argv_scan(argv,optv,&ctx,0); @@ -780,6 +1060,7 @@ static void argv_usage_impl( { const struct argv_option ** optv; const struct argv_option * option; + int nlong; bool fshort,flong,fboth; size_t len,optlen,desclen; char cache; @@ -812,7 +1093,7 @@ static void argv_usage_impl( if (header) argv_dprintf(fd,"%s",header); - for (optlen=0,optv=options; *optv; optv++) { + for (optlen=0,nlong=0,optv=options; *optv; optv++) { option = *optv; /* indent + comma */ @@ -831,6 +1112,11 @@ static void argv_usage_impl( /* optlen */ if (len > optlen) optlen = len; + + /* long (vs. hybrid-only) option? */ + if (option->long_name) + if (!(option->flags & ARGV_OPTION_HYBRID_ONLY)) + nlong++; } if (optlen >= optcap) { @@ -851,7 +1137,7 @@ static void argv_usage_impl( /* color */ if (fcolor) { color = (color == ccyan) ? cblue : ccyan; - argv_dprintf(fd,color); + argv_dprintf(fd,color,0); } /* description, using either paradigm or argname if applicable */ @@ -863,7 +1149,11 @@ static void argv_usage_impl( /* long/hybrid option prefix (-/--) */ prefix = option->flags & ARGV_OPTION_HYBRID_ONLY - ? " -" : "--"; + ? " -" : " --"; + + /* avoid extra <stace> when all long opts are hybrid-only */ + if (nlong == 0) + prefix++; /* option string */ if (fboth && option->short_name && option->long_name) diff --git a/src/internal/mdso_errinfo_impl.c b/src/internal/mdso_errinfo_impl.c index d7ea6ae..28a663c 100644 --- a/src/internal/mdso_errinfo_impl.c +++ b/src/internal/mdso_errinfo_impl.c @@ -1,6 +1,6 @@ /****************************************************************/ /* mdso: midipix dso scavenger */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ /****************************************************************/ diff --git a/src/internal/mdso_errinfo_impl.h b/src/internal/mdso_errinfo_impl.h index 4b4b693..6c83033 100644 --- a/src/internal/mdso_errinfo_impl.h +++ b/src/internal/mdso_errinfo_impl.h @@ -1,6 +1,6 @@ /****************************************************************/ /* mdso: midipix dso scavenger */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ /****************************************************************/ diff --git a/src/internal/mdso_hexfmt_impl.c b/src/internal/mdso_hexfmt_impl.c new file mode 100644 index 0000000..33d337b --- /dev/null +++ b/src/internal/mdso_hexfmt_impl.c @@ -0,0 +1,35 @@ +/****************************************************************/ +/* mdso: midipix dso scavenger */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ +/* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ +/****************************************************************/ + +#include <stdint.h> + +char buf[256] = {0}; + +static unsigned char mdso_hexfmt[16] = { + '0','1','2','3','4','5','6','7', + '8','9','a','b','c','d','e','f', +}; + +void mdso_write_hex_64(char * ch, uint64_t val) +{ + ch[0xf] = mdso_hexfmt[val % 16]; val >>= 4; + ch[0xe] = mdso_hexfmt[val % 16]; val >>= 4; + ch[0xd] = mdso_hexfmt[val % 16]; val >>= 4; + ch[0xc] = mdso_hexfmt[val % 16]; val >>= 4; + ch[0xb] = mdso_hexfmt[val % 16]; val >>= 4; + ch[0xa] = mdso_hexfmt[val % 16]; val >>= 4; + ch[0x9] = mdso_hexfmt[val % 16]; val >>= 4; + ch[0x8] = mdso_hexfmt[val % 16]; val >>= 4; + + ch[0x7] = mdso_hexfmt[val % 16]; val >>= 4; + ch[0x6] = mdso_hexfmt[val % 16]; val >>= 4; + ch[0x5] = mdso_hexfmt[val % 16]; val >>= 4; + ch[0x4] = mdso_hexfmt[val % 16]; val >>= 4; + ch[0x3] = mdso_hexfmt[val % 16]; val >>= 4; + ch[0x2] = mdso_hexfmt[val % 16]; val >>= 4; + ch[0x1] = mdso_hexfmt[val % 16]; val >>= 4; + ch[0x0] = mdso_hexfmt[val % 16]; val >>= 4; +} diff --git a/src/internal/mdso_hexfmt_impl.h b/src/internal/mdso_hexfmt_impl.h new file mode 100644 index 0000000..1ad74d1 --- /dev/null +++ b/src/internal/mdso_hexfmt_impl.h @@ -0,0 +1,14 @@ +/****************************************************************/ +/* mdso: midipix dso scavenger */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ +/* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ +/****************************************************************/ + +#ifndef MDSO_HEXFMT_IMPL_H +#define MDSO_HEXFMT_IMPL_H + +#include <stdint.h> + +void mdso_write_hex_64(char * ch, uint64_t val); + +#endif diff --git a/src/internal/mdso_object_impl.h b/src/internal/mdso_object_impl.h index 3442856..539a77d 100644 --- a/src/internal/mdso_object_impl.h +++ b/src/internal/mdso_object_impl.h @@ -1,6 +1,6 @@ /****************************************************************/ /* mdso: midipix dso scavenger */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ /****************************************************************/ @@ -31,3 +31,17 @@ static inline void mdso_obj_write_quad(unsigned char * ch, uint64_t val) ch[6] = val >> 48; ch[7] = val >> 56; } + +static inline void mdso_obj_write_dec(unsigned char * ch, uint64_t dec) +{ + int digits; + uint64_t val; + + *ch = '0'; + + for (digits=0,val=dec; val; digits++) + val /= 10; + + for (val=dec; val; val/=10) + ch[--digits] = (val % 10) + '0'; +} diff --git a/src/internal/perk/perk_structs.h b/src/internal/perk/perk_structs.h index 4dd2ffc..9ffb480 100644 --- a/src/internal/perk/perk_structs.h +++ b/src/internal/perk/perk_structs.h @@ -326,13 +326,13 @@ struct pe_raw_coff_symbol_name { unsigned char cs_zeroes [0x04]; /* 0x00 */ unsigned char cs_offset [0x04]; /* 0x04 */ } long_name; - }; + } cs_u; }; struct pe_raw_coff_strtbl { unsigned char cst_size [0x04]; /* 0x00 */ - unsigned char cst_data[]; /* 0x04 */ + unsigned char cst_data []; /* 0x04 */ }; diff --git a/src/logic/mdso_asmgen_dsometa.c b/src/logic/mdso_asmgen_dsometa.c index 497b2e2..c0ef1ca 100644 --- a/src/logic/mdso_asmgen_dsometa.c +++ b/src/logic/mdso_asmgen_dsometa.c @@ -1,6 +1,6 @@ /****************************************************************/ /* mdso: midipix dso scavenger */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ /****************************************************************/ diff --git a/src/logic/mdso_asmgen_symentry.c b/src/logic/mdso_asmgen_symentry.c index 28785ed..d4c6892 100644 --- a/src/logic/mdso_asmgen_symentry.c +++ b/src/logic/mdso_asmgen_symentry.c @@ -1,6 +1,6 @@ /****************************************************************/ /* mdso: midipix dso scavenger */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ /****************************************************************/ @@ -1,6 +1,6 @@ /****************************************************************/ /* mdso: midipix dso scavenger */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ /****************************************************************/ diff --git a/src/object/mdso_objgen_dsometa.c b/src/object/mdso_objgen_dsometa.c index 1d3725e..138a4b3 100644 --- a/src/object/mdso_objgen_dsometa.c +++ b/src/object/mdso_objgen_dsometa.c @@ -1,6 +1,6 @@ /****************************************************************/ /* mdso: midipix dso scavenger */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ /****************************************************************/ @@ -18,6 +18,11 @@ #include "perk_consts.h" #include "perk_structs.h" +struct pe_raw_coff_strtbl_impl { + unsigned char cst_size [0x04]; + unsigned char cst_data [0x10]; +}; + struct mdso_unified_record { unsigned char data[80]; }; @@ -28,7 +33,7 @@ struct mdso_dsometa_object { struct mdso_unified_record rec[1]; struct pe_raw_coff_reloc rel[1]; struct pe_raw_coff_symbol sym[8]; - struct pe_raw_coff_strtbl cst; + struct pe_raw_coff_strtbl_impl cst; }; int mdso_objgen_dsometa( diff --git a/src/object/mdso_objgen_symentry.c b/src/object/mdso_objgen_symentry.c index 22adfbb..9303a1e 100644 --- a/src/object/mdso_objgen_symentry.c +++ b/src/object/mdso_objgen_symentry.c @@ -1,6 +1,6 @@ /****************************************************************/ /* mdso: midipix dso scavenger */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ /****************************************************************/ @@ -18,6 +18,11 @@ #include "perk_consts.h" #include "perk_structs.h" +struct pe_raw_coff_strtbl_impl { + unsigned char cst_size [0x04]; + unsigned char cst_data [0x10]; +}; + struct mdso_symfn_refs { unsigned char refs[16]; }; @@ -28,9 +33,68 @@ struct mdso_symentry_object { struct mdso_symfn_refs ref[1]; struct pe_raw_coff_reloc rel[2]; struct pe_raw_coff_symbol sym[9]; - struct pe_raw_coff_strtbl cst; + struct pe_raw_coff_strtbl_impl cst; }; +static void mdso_obj_write_secoff(unsigned char * ch, uint64_t secoff) +{ + *ch++ = '/'; + mdso_obj_write_dec(ch,secoff); +} + +static void mdso_obj_write_sym_symentry(char * ch, const char * sym) +{ + *ch++ = '.'; + + for (; *sym; ) + *ch++ = *sym++; + + memcpy(ch,"_symentry.s",11); +} + +static void mdso_obj_write_sym_symstr(char * ch, const char * sym) +{ + memcpy(ch,".symstr_",8); + ch = &ch[8]; + + for (; *sym; ) + *ch++ = *sym++; +} + +static void mdso_obj_write_sym_impstr(char * ch, uint32_t uscore, const char * sym) +{ + memcpy(ch,"__imp_",6); + ch = &ch[6]; + + if (uscore) + *ch++ = '_'; + + for (; *sym; ) + *ch++ = *sym++; +} + +static void mdso_obj_write_sym_secstr(char * ch, const char * secname, const char * sym) +{ + for (; *secname; ) + *ch++ = *secname++; + + *ch++ = '$'; + + for (; *sym; ) + *ch++ = *sym++; +} + +static void mdso_obj_write_libname(char * ch, const char * secname, const char * sym) +{ + for (; *secname; ) + *ch++ = *secname++; + + *ch++ = '_'; + + for (; *sym; ) + *ch++ = *sym++; +} + int mdso_objgen_symentry( const struct mdso_driver_ctx * dctx, const char * sym, @@ -42,6 +106,7 @@ int mdso_objgen_symentry( void * mark; char * ch; char * strtbl; + const char * src; struct pe_raw_aux_rec_section * aux; size_t liblen; uint32_t symlen; @@ -147,13 +212,13 @@ int mdso_objgen_symentry( mdso_obj_write_short(syment->hdr.cfh_characteristics,oattr); /* .dsostrs section header */ - sprintf((char *)syment->sec[0].sh_name,"/%d",stroff_dsostrs); + mdso_obj_write_secoff(syment->sec[0].sh_name,stroff_dsostrs); mdso_obj_write_long(syment->sec[0].sh_size_of_raw_data,symlen+1); mdso_obj_write_long(syment->sec[0].sh_ptr_to_raw_data,stroff); mdso_obj_write_long(syment->sec[0].sh_characteristics,sattr); /* .dsosyms section header */ - sprintf((char *)syment->sec[1].sh_name,"/%d",stroff_dsosyms); + mdso_obj_write_secoff(syment->sec[1].sh_name,stroff_dsosyms); mdso_obj_write_long(syment->sec[1].sh_size_of_raw_data,2*relrva); mdso_obj_write_long(syment->sec[1].sh_ptr_to_raw_data,refoff); mdso_obj_write_long(syment->sec[1].sh_ptr_to_relocs,reloff); @@ -186,7 +251,7 @@ int mdso_objgen_symentry( mdso_obj_write_long(&symrec[1].cs_name[4],stroff_file); memcpy(symrec[0].cs_name,".file",5); - sprintf(&strtbl[stroff_file],".%s_symentry.s",sym); + mdso_obj_write_sym_symentry(&strtbl[stroff_file],sym); symrec += 2; @@ -196,7 +261,7 @@ int mdso_objgen_symentry( mdso_obj_write_short(symrec[0].cs_section_number,1); mdso_obj_write_long(&symrec[0].cs_name[4],stroff_dsostrs); - sprintf(&strtbl[stroff_dsostrs],"%s$%s",MDSO_STRS_SECTION,sym); + mdso_obj_write_sym_secstr(&strtbl[stroff_dsostrs],MDSO_STRS_SECTION,sym); aux = (struct pe_raw_aux_rec_section *)&symrec[1]; mdso_obj_write_long(aux->aux_size,symlen+1); @@ -210,7 +275,7 @@ int mdso_objgen_symentry( mdso_obj_write_short(symrec[0].cs_section_number,2); mdso_obj_write_long(&symrec[0].cs_name[4],stroff_dsosyms); - sprintf(&strtbl[stroff_dsosyms],"%s$%s",MDSO_SYMS_SECTION,sym); + mdso_obj_write_sym_secstr(&strtbl[stroff_dsosyms],MDSO_SYMS_SECTION,sym); aux = (struct pe_raw_aux_rec_section *)&symrec[1]; mdso_obj_write_long(aux->aux_size,2*relrva); @@ -224,7 +289,7 @@ int mdso_objgen_symentry( mdso_obj_write_short(symrec[0].cs_section_number,1); mdso_obj_write_long(&symrec[0].cs_name[4],stroff_symstr); - sprintf(&strtbl[stroff_symstr],".symstr_%s",sym); + mdso_obj_write_sym_symstr(&strtbl[stroff_symstr],sym); symrec += 1; @@ -234,13 +299,18 @@ int mdso_objgen_symentry( mdso_obj_write_short(symrec[0].cs_section_number,2); mdso_obj_write_long(&symrec[0].cs_name[4],stroff_impsym); - sprintf(&strtbl[stroff_impsym],"__imp_%s%s",uscore ? "_" : "", sym); + mdso_obj_write_sym_impstr(&strtbl[stroff_impsym],uscore,sym); symrec += 1; /* archive symbol map */ - if (vobj->mapstrs) - strcpy(vobj->mapstrs,&strtbl[stroff_impsym]); + if (vobj->mapstrs) { + ch = vobj->mapstrs; + src = &strtbl[stroff_impsym]; + + for (; *src; ) + *ch++ = *src++; + } /* coff symbol: .dsometa_libname */ symrec[0].cs_storage_class[0] = PE_IMAGE_SYM_CLASS_EXTERNAL; @@ -249,7 +319,7 @@ int mdso_objgen_symentry( mdso_obj_write_short(symrec[0].cs_section_number,0); mdso_obj_write_long(&symrec[0].cs_name[4],stroff_libname); - sprintf(&strtbl[stroff_libname],"%s_%s", + mdso_obj_write_libname(&strtbl[stroff_libname], MDSO_META_SECTION, dctx->cctx->libname); diff --git a/src/output/mdso_output_error.c b/src/output/mdso_output_error.c index cc97c18..9e03448 100644 --- a/src/output/mdso_output_error.c +++ b/src/output/mdso_output_error.c @@ -1,6 +1,6 @@ /****************************************************************/ /* mdso: midipix dso scavenger */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ /****************************************************************/ diff --git a/src/output/mdso_output_export_symbols.c b/src/output/mdso_output_export_symbols.c index fefb6ce..5e22433 100644 --- a/src/output/mdso_output_export_symbols.c +++ b/src/output/mdso_output_export_symbols.c @@ -1,6 +1,6 @@ /****************************************************************/ /* mdso: midipix dso scavenger */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ /****************************************************************/ diff --git a/src/output/mdso_output_expsyms_crc.c b/src/output/mdso_output_expsyms_crc.c index 5b42ee8..75202bf 100644 --- a/src/output/mdso_output_expsyms_crc.c +++ b/src/output/mdso_output_expsyms_crc.c @@ -1,6 +1,6 @@ /****************************************************************/ /* mdso: midipix dso scavenger */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ /****************************************************************/ @@ -22,7 +22,7 @@ static int pretty_expsym_crc32( const char * name) { return mdso_dprintf( - fdout,"%" PRIx32 " %s\n", + fdout,"%08" PRIx32 " %s\n", mdso_crc32_mbstr((const unsigned char *)name,0), name); } @@ -32,7 +32,7 @@ static int pretty_expsym_crc64( const char * name) { return mdso_dprintf( - fdout,"%" PRIx64 " %s\n", + fdout,"%016" PRIx64 " %s\n", mdso_crc64_mbstr((const unsigned char *)name,0), name); } diff --git a/src/util/mdso_create_implib_archive.c b/src/util/mdso_create_implib_archive.c index 00014c4..13e5747 100644 --- a/src/util/mdso_create_implib_archive.c +++ b/src/util/mdso_create_implib_archive.c @@ -1,6 +1,6 @@ /****************************************************************/ /* mdso: midipix dso scavenger */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ /****************************************************************/ diff --git a/src/util/mdso_create_implib_objects.c b/src/util/mdso_create_implib_objects.c index 4e92a66..d165c34 100644 --- a/src/util/mdso_create_implib_objects.c +++ b/src/util/mdso_create_implib_objects.c @@ -1,6 +1,6 @@ /****************************************************************/ /* mdso: midipix dso scavenger */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ /****************************************************************/ @@ -9,19 +9,50 @@ #include <string.h> #include <mdso/mdso.h> +#include "mdso_hexfmt_impl.h" #include "mdso_errinfo_impl.h" -static void mdso_init_objname(char * buf, const char * fmt, const char * str) +static void mdso_init_symentry(char * ch, const char * str) { - char hexstr[24]; - long long unsigned int crc64; - - if (strlen(str) + strlen(fmt) > (PATH_MAX - 1)) { - crc64 = mdso_crc64_mbstr((const unsigned char *)str,0); - sprintf(hexstr,"%llx",crc64); - sprintf(buf,fmt,hexstr); - } else - sprintf(buf,fmt,str); + uint64_t crc64; + unsigned slen = 11; + + ch[0] = '.'; + ch++; + + if (strlen(str) > (PATH_MAX - slen - 1)) { + crc64 = mdso_crc64_mbstr((unsigned char *)str,0); + mdso_write_hex_64(ch,crc64); + ch = &ch[16]; + } else { + for (; *str; ) + *ch++ = *str++; + } + + memcpy(ch,"_symentry.o",slen); + ch[slen] = '\0'; +} + +static void mdso_init_dsometa(char * ch, const char * str) +{ + uint64_t crc64; + unsigned slen = 9; + + memcpy(ch,".dsometa_",slen); + ch = &ch[slen]; + + if (strlen(str) > (PATH_MAX - slen - 1)) { + crc64 = mdso_crc64_mbstr((unsigned char *)str,0); + mdso_write_hex_64(ch,crc64); + ch = &ch[16]; + } else { + for (; *str; ) + *ch++ = *str++; + } + + ch[0] = '.'; + ch[1] = 'o'; + ch[2] = '\0'; } static void mdso_init_object(struct mdso_object * obj, const char * objname) @@ -44,7 +75,7 @@ int mdso_create_implib_objects(const struct mdso_driver_ctx * dctx) return MDSO_NESTED_ERROR(dctx); for (sym=uctx->syms; *sym; sym++) { - mdso_init_objname(objname,".%s_symentry.o",*sym); + mdso_init_symentry(objname,*sym); mdso_init_object(&obj,objname); if (mdso_objgen_symentry(dctx,*sym,&obj) < 0) @@ -55,7 +86,7 @@ int mdso_create_implib_objects(const struct mdso_driver_ctx * dctx) } /* dsometa */ - mdso_init_objname(objname,".dsometa_%s.o",dctx->cctx->libname); + mdso_init_dsometa(objname,dctx->cctx->libname); mdso_init_object(&obj,objname); if (mdso_objgen_dsometa(dctx,&obj) < 0) diff --git a/src/util/mdso_create_implib_sources.c b/src/util/mdso_create_implib_sources.c index df36eff..5d002d5 100644 --- a/src/util/mdso_create_implib_sources.c +++ b/src/util/mdso_create_implib_sources.c @@ -1,6 +1,6 @@ /****************************************************************/ /* mdso: midipix dso scavenger */ -/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ /****************************************************************/ @@ -10,21 +10,51 @@ #include <mdso/mdso.h> #include "mdso_driver_impl.h" +#include "mdso_hexfmt_impl.h" #include "mdso_errinfo_impl.h" -static void mdso_init_asmname(char * buf, const char * fmt, const char * str) +static void mdso_init_symentry(char * ch, const char * str) { - char hexstr[24]; - long long unsigned int crc64; - - if (strlen(str) + strlen(fmt) > (PATH_MAX - 1)) { - crc64 = mdso_crc64_mbstr((const unsigned char *)str,0); - sprintf(hexstr,"%llx",crc64); - sprintf(buf,fmt,hexstr); - } else - sprintf(buf,fmt,str); + uint64_t crc64; + unsigned slen = 11; + + ch[0] = '.'; + ch++; + + if (strlen(str) > (PATH_MAX - slen - 1)) { + crc64 = mdso_crc64_mbstr((unsigned char *)str,0); + mdso_write_hex_64(ch,crc64); + ch = &ch[16]; + } else { + for (; *str; ) + *ch++ = *str++; + } + + memcpy(ch,"_symentry.s",slen); + ch[slen] = '\0'; } +static void mdso_init_dsometa(char * ch, const char * str) +{ + uint64_t crc64; + unsigned slen = 9; + + memcpy(ch,".dsometa_",slen); + ch = &ch[slen]; + + if (strlen(str) > (PATH_MAX - slen - 1)) { + crc64 = mdso_crc64_mbstr((unsigned char *)str,0); + mdso_write_hex_64(ch,crc64); + ch = &ch[16]; + } else { + for (; *str; ) + *ch++ = *str++; + } + + ch[0] = '.'; + ch[1] = 's'; + ch[2] = '\0'; +} int mdso_create_implib_sources(const struct mdso_driver_ctx * dctx) { struct mdso_unit_ctx * uctx; @@ -41,7 +71,7 @@ int mdso_create_implib_sources(const struct mdso_driver_ctx * dctx) return MDSO_NESTED_ERROR(dctx); for (sym=uctx->syms; *sym; sym++) { - mdso_init_asmname(asmname,".%s_symentry.s",*sym); + mdso_init_symentry(asmname,*sym); if ((fdout = mdso_create_asmsrc(dctx,asmname)) < 0) return MDSO_NESTED_ERROR(dctx); @@ -59,7 +89,7 @@ int mdso_create_implib_sources(const struct mdso_driver_ctx * dctx) } /* dsometa */ - mdso_init_asmname(asmname,".dsometa_%s.s",dctx->cctx->libname); + mdso_init_dsometa(asmname,dctx->cctx->libname); if ((fdout = mdso_create_asmsrc(dctx,asmname)) < 0) return MDSO_NESTED_ERROR(dctx); |