diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index 1d2ab7c81eda..6d515dca05ac 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -94,10 +94,10 @@ static tree handle_constructor_attribute (tree *, tree, tree, int, bool *); static tree handle_destructor_attribute (tree *, tree, tree, int, bool *); static tree handle_mode_attribute (tree *, tree, tree, int, bool *); static tree handle_section_attribute (tree *, tree, tree, int, bool *); +static tree handle_special_var_sec_attribute (tree *, tree, tree, int, bool *); static tree handle_aligned_attribute (tree *, tree, tree, int, bool *); static tree handle_warn_if_not_aligned_attribute (tree *, tree, tree, int, bool *); -static tree handle_noinit_attribute (tree *, tree, tree, int, bool *); static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ; static tree handle_noplt_attribute (tree *, tree, tree, int, bool *) ; static tree handle_alias_ifunc_attribute (bool, tree *, tree, tree, bool *); @@ -248,9 +248,12 @@ static const struct attribute_spec::exclusions attr_const_pure_exclusions[] = ATTR_EXCL (NULL, false, false, false) }; -static const struct attribute_spec::exclusions attr_noinit_exclusions[] = +/* Exclusions that apply to attributes that put declarations in specific + sections. */ +static const struct attribute_spec::exclusions attr_section_exclusions[] = { ATTR_EXCL ("noinit", true, true, true), + ATTR_EXCL ("persistent", true, true, true), ATTR_EXCL ("section", true, true, true), ATTR_EXCL (NULL, false, false, false), }; @@ -339,7 +342,7 @@ const struct attribute_spec c_common_attribute_table[] = { "mode", 1, 1, false, true, false, false, handle_mode_attribute, NULL }, { "section", 1, 1, true, false, false, false, - handle_section_attribute, attr_noinit_exclusions }, + handle_section_attribute, attr_section_exclusions }, { "aligned", 0, 1, false, false, false, false, handle_aligned_attribute, attr_aligned_exclusions }, @@ -509,7 +512,9 @@ const struct attribute_spec c_common_attribute_table[] = { "copy", 1, 1, false, false, false, false, handle_copy_attribute, NULL }, { "noinit", 0, 0, true, false, false, false, - handle_noinit_attribute, attr_noinit_exclusions }, + handle_special_var_sec_attribute, attr_section_exclusions }, + { "persistent", 0, 0, true, false, false, false, + handle_special_var_sec_attribute, attr_section_exclusions }, { "access", 1, 3, false, true, true, false, handle_access_attribute, NULL }, /* Attributes used by Objective-C. */ @@ -2387,64 +2392,112 @@ handle_weak_attribute (tree *node, tree name, return NULL_TREE; } -/* Handle a "noinit" attribute; arguments as in struct - attribute_spec.handler. Check whether the attribute is allowed - here and add the attribute to the variable decl tree or otherwise - issue a diagnostic. This function checks NODE is of the expected - type and issues diagnostics otherwise using NAME. If it is not of - the expected type *NO_ADD_ATTRS will be set to true. */ - +/* Handle a "noinit" or "persistent" attribute; arguments as in + struct attribute_spec.handler. + This generic handler is used for "special variable sections" that allow the + section name to be set using a dedicated attribute. Additional validation + is performed for the specific properties of the section corresponding to the + attribute. + The ".noinit" section *is not* loaded by the program loader, and is not + initialized by the runtime startup code. + The ".persistent" section *is* loaded by the program loader, but is not + initialized by the runtime startup code. */ static tree -handle_noinit_attribute (tree * node, - tree name, - tree args, - int flags ATTRIBUTE_UNUSED, - bool *no_add_attrs) +handle_special_var_sec_attribute (tree *node, tree name, tree args, + int flags, bool *no_add_attrs) { - const char *message = NULL; + tree decl = *node; tree res = NULL_TREE; - gcc_assert (DECL_P (*node)); - gcc_assert (args == NULL); - - if (TREE_CODE (*node) != VAR_DECL) - message = G_("%qE attribute only applies to variables"); - - /* Check that it's possible for the variable to have a section. */ - else if ((TREE_STATIC (*node) || DECL_EXTERNAL (*node) || in_lto_p) - && DECL_SECTION_NAME (*node)) - message = G_("%qE attribute cannot be applied to variables " - "with specific sections"); - - else if (!targetm.have_switchable_bss_sections) - message = G_("%qE attribute is specific to ELF targets"); - - if (message) + /* First perform generic validation common to "noinit" and "persistent" + attributes. */ + if (!targetm_common.have_named_sections) { - warning (OPT_Wattributes, message, name); - *no_add_attrs = true; + error_at (DECL_SOURCE_LOCATION (decl), + "section attributes are not supported for this target"); + goto fail; } - else + + if (!VAR_P (decl)) { - res = targetm.handle_generic_attribute (node, name, args, flags, - no_add_attrs); - /* If the back end confirms the attribute can be added then continue onto - final processing. */ - if (!(*no_add_attrs)) + warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes, + "ignoring %qE attribute not set on a variable", + name); + goto fail; + } + + if (VAR_P (decl) + && current_function_decl != NULL_TREE + && !TREE_STATIC (decl)) + { + error_at (DECL_SOURCE_LOCATION (decl), + "%qE attribute cannot be specified for local variables", + name); + goto fail; + } + + if (VAR_P (decl) + && !targetm.have_tls && targetm.emutls.tmpl_section + && DECL_THREAD_LOCAL_P (decl)) + { + error ("section of %q+D cannot be overridden", decl); + goto fail; + } + + if (!targetm.have_switchable_bss_sections) + { + error ("%qE attribute is specific to ELF targets", name); + goto fail; + } + + if (TREE_READONLY (decl)) + { + warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes, + "ignoring %qE attribute set on const variable", + name); + goto fail; + } + + /* Now validate noinit/persistent individually. */ + if (strcmp (IDENTIFIER_POINTER (name), "noinit") == 0) + { + if (DECL_INITIAL (decl)) { - /* If this var is thought to be common, then change this. Common - variables are assigned to sections before the backend has a - chance to process them. Do this only if the attribute is - valid. */ - if (DECL_COMMON (*node)) - DECL_COMMON (*node) = 0; + warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes, + "ignoring %qE attribute set on initialized variable", + name); + goto fail; + } + /* If this var is thought to be common, then change this. "noinit" + variables must be placed in an explicit ".noinit" section. */ + DECL_COMMON (decl) = 0; + } + else if (strcmp (IDENTIFIER_POINTER (name), "persistent") == 0) + { + if (DECL_COMMON (decl) || DECL_INITIAL (decl) == NULL_TREE) + { + warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes, + "ignoring %qE attribute set on uninitialized variable", + name); + goto fail; } } + else + gcc_unreachable (); + res = targetm.handle_generic_attribute (node, name, args, flags, + no_add_attrs); + + /* If the back end confirms the attribute can be added then continue onto + final processing. */ + if (!(*no_add_attrs)) + return res; + +fail: + *no_add_attrs = true; return res; } - /* Handle a "noplt" attribute; arguments as in struct attribute_spec.handler. */ diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index f0269422ca21..6018347daed5 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -7426,9 +7426,23 @@ The @code{weak} attribute is described in @cindex @code{noinit} variable attribute Any data with the @code{noinit} attribute will not be initialized by the C runtime startup code, or the program loader. Not initializing -data in this way can reduce program startup times. This attribute is -specific to ELF targets and relies on the linker to place such data in -the right location +data in this way can reduce program startup times. + +This attribute is specific to ELF targets and relies on the linker +script to place sections with the @code{.noinit} prefix in the right +location. + +@item persistent +@cindex @code{persistent} variable attribute +Any data with the @code{persistent} attribute will not be initialized by +the C runtime startup code, but will be initialized by the program +loader. This enables the value of the variable to @samp{persist} +between processor resets. + +This attribute is specific to ELF targets and relies on the linker +script to place the sections with the @code{.persistent} prefix in the +right location. Specifically, some type of non-volatile, writeable +memory is required. @item objc_nullability (@var{nullability kind}) @r{(Objective-C and Objective-C++ only)} @cindex @code{objc_nullability} variable attribute diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi index 566fda02c306..852eaa2e6765 100644 --- a/gcc/doc/sourcebuild.texi +++ b/gcc/doc/sourcebuild.texi @@ -2548,6 +2548,9 @@ Target does not generate PIC by default. @item offload_gcn Target has been configured for OpenACC/OpenMP offloading on AMD GCN. +@item persistent +Target supports the @code{persistent} variable attribute. + @item pie_enabled Target generates PIE by default. diff --git a/gcc/testsuite/c-c++-common/torture/attr-noinit-1.c b/gcc/testsuite/c-c++-common/torture/attr-noinit-1.c new file mode 100644 index 000000000000..877e7647ac9a --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/attr-noinit-1.c @@ -0,0 +1,7 @@ +/* { dg-do run } */ +/* { dg-require-effective-target noinit } */ +/* { dg-skip-if "data LMA != VMA" { msp430-*-* } { "-mlarge" } } */ +/* { dg-options "-save-temps" } */ +/* { dg-final { scan-assembler ".section\t.noinit,\"aw\"\n" } } */ + +#include "attr-noinit-main.inc" diff --git a/gcc/testsuite/c-c++-common/torture/attr-noinit-2.c b/gcc/testsuite/c-c++-common/torture/attr-noinit-2.c new file mode 100644 index 000000000000..befa2a0bd522 --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/attr-noinit-2.c @@ -0,0 +1,8 @@ +/* { dg-do run } */ +/* { dg-require-effective-target noinit } */ +/* { dg-options "-fdata-sections -save-temps" } */ +/* { dg-skip-if "data LMA != VMA" { msp430-*-* } { "-mlarge" } } */ +/* { dg-final { scan-assembler ".section\t.noinit.var_noinit,\"aw\"\n" } } */ + +/* Test the "noinit" attribute with -fdata-sections. */ +#include "attr-noinit-main.inc" diff --git a/gcc/testsuite/c-c++-common/torture/attr-noinit-3.c b/gcc/testsuite/c-c++-common/torture/attr-noinit-3.c new file mode 100644 index 000000000000..519e88a59a60 --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/attr-noinit-3.c @@ -0,0 +1,11 @@ +/* { dg-do run } */ +/* { dg-require-effective-target noinit } */ +/* { dg-options "-flto -save-temps" } */ +/* { dg-skip-if "data LMA != VMA" { msp430-*-* } { "-mlarge" } } */ +/* { dg-final { scan-file attr-noinit-3.ltrans0.ltrans.s ".section\t\.noinit,\"aw\"\n" } } */ + +/* Test the "noinit" attribute with -flto. Specifically examine the + final LTO assembly file, to ensure the "noinit" setting on the variable + hasn't been lost. */ +#include "attr-noinit-main.inc" + diff --git a/gcc/testsuite/c-c++-common/torture/attr-noinit-invalid.c b/gcc/testsuite/c-c++-common/torture/attr-noinit-invalid.c new file mode 100644 index 000000000000..c3b5fffd166f --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/attr-noinit-invalid.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target noinit } */ +/* { dg-options "-Wattributes" } */ + +/* Check warning/error messages for "noinit" attribute misuse. */ +int __attribute__((noinit)) noinit_fn (void); /* { dg-warning "ignoring 'noinit' attribute not set on a variable" } */ +int __attribute__((section ("mysection"), noinit)) noinit_section1; /* { dg-warning "because it conflicts with attribute" } */ +int __attribute__((noinit, section ("mysection"))) noinit_section2; /* { dg-warning "because it conflicts with attribute" } */ +const int __attribute__((noinit)) noinit_const; /* { dg-warning "ignoring 'noinit' attribute set on const variable" } */ +/* { dg-error "uninitialized 'const noinit_const'" "" { target c++ } .-1 } */ +int __attribute__((noinit)) noinit_init = 42; /* { dg-warning "ignoring 'noinit' attribute set on initialized variable" } */ +void foo (void) { int __attribute__((noinit)) local_noinit; } /* { dg-error "'noinit' attribute cannot be specified for local variables" } */ diff --git a/gcc/testsuite/gcc.c-torture/execute/noinit-attribute.c b/gcc/testsuite/c-c++-common/torture/attr-noinit-main.inc similarity index 55% rename from gcc/testsuite/gcc.c-torture/execute/noinit-attribute.c rename to gcc/testsuite/c-c++-common/torture/attr-noinit-main.inc index c8fa22bf38b8..92cdb9b85347 100644 --- a/gcc/testsuite/gcc.c-torture/execute/noinit-attribute.c +++ b/gcc/testsuite/c-c++-common/torture/attr-noinit-main.inc @@ -1,16 +1,16 @@ -/* { dg-do run } */ -/* { dg-require-effective-target noinit } */ -/* { dg-options "-Wattributes" } */ -/* { dg-skip-if "data LMA != VMA" { msp430-*-* } { "-mlarge" } } */ - -/* This test checks that noinit data is handled correctly. +/* This test checks that data marked with the "noinit" attribute is handled + correctly. If data LMA != VMA (e.g. for simulating the copy of data from ROM to RAM), then var_init will always be re-initialized to 2 and this test will loop - forever. */ + forever, so it must be skipped for those targets. */ +#ifdef __cplusplus +extern "C" { +#endif extern void _start (void) __attribute__ ((noreturn)); -extern void abort (void) __attribute__ ((noreturn)); -extern void exit (int) __attribute__ ((noreturn)); +#ifdef __cplusplus +} +#endif int var_common; int var_zero = 0; @@ -18,24 +18,19 @@ int var_one = 1; int __attribute__((noinit)) var_noinit; int var_init = 2; -int __attribute__((noinit)) func(); /* { dg-warning "attribute only applies to variables" } */ -int __attribute__((section ("mysection"), noinit)) var_section1; /* { dg-warning "because it conflicts with attribute" } */ -int __attribute__((noinit, section ("mysection"))) var_section2; /* { dg-warning "because it conflicts with attribute" } */ - - int main (void) { /* Make sure that the C startup code has correctly initialized the ordinary variables. */ if (var_common != 0) - abort (); + __builtin_abort (); /* Initialized variables are not re-initialized during startup, so check their original values only during the first run of this test. */ if (var_init == 2) if (var_zero != 0 || var_one != 1) - abort (); + __builtin_abort (); switch (var_init) { @@ -45,19 +40,19 @@ main (void) break; case 3: - /* Second time through - make sure that d has not been reset. */ + /* Second time through - make sure that var_noinit has not been reset. */ if (var_noinit != 3) - abort (); - exit (0); + __builtin_abort (); + __builtin_exit (0); default: /* Any other value for var_init is an error. */ - abort (); + __builtin_abort (); } /* Simulate a processor reset by calling the C startup code. */ _start (); /* Should never reach here. */ - abort (); + __builtin_abort (); } diff --git a/gcc/testsuite/c-c++-common/torture/attr-persistent-1.c b/gcc/testsuite/c-c++-common/torture/attr-persistent-1.c new file mode 100644 index 000000000000..72dc3c271928 --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/attr-persistent-1.c @@ -0,0 +1,8 @@ +/* { dg-do run } */ +/* { dg-require-effective-target persistent } */ +/* { dg-skip-if "data LMA != VMA" { msp430-*-* } { "-mlarge" } } */ +/* { dg-options "-save-temps" } */ +/* { dg-final { scan-assembler ".section\t.persistent,\"aw\"\n" } } */ + +/* Test the "persistent" attribute. */ +#include "attr-persistent-main.inc" diff --git a/gcc/testsuite/c-c++-common/torture/attr-persistent-2.c b/gcc/testsuite/c-c++-common/torture/attr-persistent-2.c new file mode 100644 index 000000000000..a7de0d5d38ba --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/attr-persistent-2.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target persistent } */ +/* { dg-skip-if "data LMA != VMA" { msp430-*-* } { "-mlarge" } } */ +/* { dg-options "-fdata-sections -save-temps" } */ +/* { dg-final { scan-assembler ".section\t.persistent.var_persistent,\"aw\"\n" } } */ + +/* Test the "persistent" attribute with -fdata-sections. */ +#include "attr-persistent-main.inc" diff --git a/gcc/testsuite/c-c++-common/torture/attr-persistent-3.c b/gcc/testsuite/c-c++-common/torture/attr-persistent-3.c new file mode 100644 index 000000000000..3e4fd28618d9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/attr-persistent-3.c @@ -0,0 +1,10 @@ +/* { dg-do run } */ +/* { dg-require-effective-target persistent } */ +/* { dg-options "-flto -save-temps" } */ +/* { dg-skip-if "data LMA != VMA" { msp430-*-* } { "-mlarge" } } */ +/* { dg-final { scan-file attr-persistent-3.ltrans0.ltrans.s ".section\t\.persistent,\"aw\"\n" } } */ + +/* Test the "persistent" attribute with -flto. Specifically examine the + final LTO assembly file, to ensure the "persistent" setting on the variable + hasn't been lost. */ +#include "attr-persistent-main.inc" diff --git a/gcc/testsuite/c-c++-common/torture/attr-persistent-invalid.c b/gcc/testsuite/c-c++-common/torture/attr-persistent-invalid.c new file mode 100644 index 000000000000..06d9f3536295 --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/attr-persistent-invalid.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target persistent } */ +/* { dg-options "-Wattributes" } */ + +/* Check warning/error messages for "persistent" attribute misuse. */ +int __attribute__((persistent)) persistent_fn (void); /* { dg-warning "ignoring 'persistent' attribute not set on a variable" } */ +int __attribute__((section ("mysection"), persistent)) persistent_section1 = 1; /* { dg-warning "because it conflicts with attribute" } */ +int __attribute__((persistent, section ("mysection"))) persistent_section2 = 2; /* { dg-warning "because it conflicts with attribute" } */ +const int __attribute__((persistent)) persistent_const = 3; /* { dg-warning "ignoring 'persistent' attribute set on const variable" } */ +int __attribute__((persistent)) persistent_init; /* { dg-warning "ignoring 'persistent' attribute set on uninitialized variable" } */ +void foo (void) { int __attribute__((persistent)) local_persistent = 4; } /* { dg-error "'persistent' attribute cannot be specified for local variables" } */ diff --git a/gcc/testsuite/c-c++-common/torture/attr-persistent-main.inc b/gcc/testsuite/c-c++-common/torture/attr-persistent-main.inc new file mode 100644 index 000000000000..a442141e55ce --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/attr-persistent-main.inc @@ -0,0 +1,58 @@ +/* This test checks that data marked with the "persistent" attribute is handled + correctly. + If data LMA != VMA (e.g. for simulating the copy of data from ROM to RAM), + then var_init will always be re-initialized to 2 and this test will loop + forever, so it must be skipped for those targets. */ + +#ifdef __cplusplus +extern "C" { +#endif +extern void _start (void) __attribute__ ((noreturn)); +#ifdef __cplusplus +} +#endif + +int var_common; +int var_zero = 0; +int var_one = 1; +int __attribute__((persistent)) var_persistent = 2; +int var_init = 2; + +int +main (void) +{ + /* Make sure that the C startup code has correctly initialized the ordinary variables. */ + if (var_common != 0) + __builtin_abort (); + + /* Initialized variables are not re-initialized during startup, so + check their original values only during the first run of this + test. */ + if (var_init == 2) + if (var_zero != 0 || var_one != 1 || var_persistent != 2) + __builtin_abort (); + + switch (var_init) + { + case 2: + /* First time through - change all the values. */ + var_common = var_zero = var_one = var_persistent = var_init = 3; + break; + + case 3: + /* Second time through - make sure that var_persistent has not been reset. */ + if (var_persistent != 3) + __builtin_abort (); + __builtin_exit (0); + + default: + /* Any other value for var_init is an error. */ + __builtin_abort (); + } + + /* Simulate a processor reset by calling the C startup code. */ + _start (); + + /* Should never reach here. */ + __builtin_abort (); +} diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 43ac526567f1..ff6bc5f4b925 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -380,6 +380,18 @@ proc check_effective_target_noinit { } { return 0 } +# The "persistent" attribute is only supported by some targets. +# This proc returns 1 if it's supported, 0 if it's not. + +proc check_effective_target_persistent { } { + if { [istarget arm*-*-eabi] + || [istarget msp430-*-*] } { + return 1 + } + + return 0 +} + ############################### # proc check_visibility_available { what_kind } ############################### diff --git a/gcc/tree.h b/gcc/tree.h index 664449aa3299..078919bce5de 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2669,6 +2669,13 @@ extern tree vector_element_bits_tree (const_tree); (DECL_P (DECL) \ && (lookup_attribute ("noinit", DECL_ATTRIBUTES (DECL)) != NULL_TREE)) +/* Nonzero for a decl that is decorated with the "persistent" attribute. + decls with this attribute are placed into the ".persistent" section, so they + are not initialized by the target's startup code. */ +#define DECL_PERSISTENT_P(DECL) \ + (DECL_P (DECL) \ + && (lookup_attribute ("persistent", DECL_ATTRIBUTES (DECL)) != NULL_TREE)) + /* For function local variables of COMPLEX and VECTOR types, indicates that the variable is not aliased, and that all modifications to the variable have been adjusted so that diff --git a/gcc/varasm.c b/gcc/varasm.c index da7d0d7d91d1..b92da26fb820 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -1057,7 +1057,11 @@ bss_initializer_p (const_tree decl, bool named) || (DECL_INITIAL (decl) == error_mark_node && !in_lto_p) || (flag_zero_initialized_in_bss - && initializer_zerop (DECL_INITIAL (decl))))); + && initializer_zerop (DECL_INITIAL (decl)) + /* A decl with the "persistent" attribute applied and + explicitly initialized to 0 should not be treated as a BSS + variable. */ + && !DECL_PERSISTENT_P (decl)))); } /* Compute the alignment of variable specified by DECL. @@ -6680,6 +6684,9 @@ default_section_type_flags (tree decl, const char *name, int reloc) if (strcmp (name, ".noinit") == 0) flags |= SECTION_WRITE | SECTION_BSS | SECTION_NOTYPE; + if (strcmp (name, ".persistent") == 0) + flags |= SECTION_WRITE | SECTION_NOTYPE; + /* Various sections have special ELF types that the assembler will assign by default based on the name. They are neither SHT_PROGBITS nor SHT_NOBITS, so when changing sections we don't want to print a @@ -7023,6 +7030,11 @@ default_elf_select_section (tree decl, int reloc, sname = ".sdata2"; break; case SECCAT_DATA: + if (DECL_P (decl) && DECL_PERSISTENT_P (decl)) + { + sname = ".persistent"; + break; + } return data_section; case SECCAT_DATA_REL: sname = ".data.rel"; @@ -7093,6 +7105,11 @@ default_unique_section (tree decl, int reloc) break; case SECCAT_DATA: prefix = one_only ? ".d" : ".data"; + if (DECL_P (decl) && DECL_PERSISTENT_P (decl)) + { + prefix = one_only ? ".p" : ".persistent"; + break; + } break; case SECCAT_DATA_REL: prefix = one_only ? ".d.rel" : ".data.rel";