aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Marchi <simon.marchi@efficios.com>2025-07-23 14:11:39 -0400
committerSimon Marchi <simon.marchi@efficios.com>2025-08-22 10:45:47 -0400
commit8a729432af7fe9e9f07036e2d0a5c66439de8bf9 (patch)
treecc224eee8aaaf5d71179c57a6756e87cba6b1442
parentfcdc6c5aff198140e0e2c8b94eef48d340e04dbc (diff)
downloadbinutils-8a729432af7fe9e9f07036e2d0a5c66439de8bf9.zip
binutils-8a729432af7fe9e9f07036e2d0a5c66439de8bf9.tar.gz
binutils-8a729432af7fe9e9f07036e2d0a5c66439de8bf9.tar.bz2
gdb/solib: adjust info linker-namespaces/sharedlibrary format
I would like to propose some minor changes to the format of "info linker namespaces" and "info sharedlibrary", to make it a bit tidier and less chatty. Here are the current formats (I replaced empty lines with dots, so that git doesn't collapse them): (gdb) info linker-namespaces There are 3 linker namespaces loaded There are 5 libraries loaded in linker namespace [[0]] Displaying libraries for linker namespace [[0]]: From To Syms Read Shared Object Library 0x00007ffff7fc6000 0x00007ffff7fff000 Yes /lib64/ld-linux-x86-64.so.2 0x00007ffff7e94000 0x00007ffff7f8c000 Yes /usr/lib/libm.so.6 0x00007ffff7ca4000 0x00007ffff7e94000 Yes /usr/lib/libc.so.6 0x00007ffff7fad000 0x00007ffff7fb2000 Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.1.so 0x00007ffff7fa8000 0x00007ffff7fad000 Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib-dep.so . . There are 6 libraries loaded in linker namespace [[1]] Displaying libraries for linker namespace [[1]]: From To Syms Read Shared Object Library 0x00007ffff7fb7000 0x00007ffff7fbc000 Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.1.so 0x00007ffff7fb2000 0x00007ffff7fb7000 Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib-dep.so 0x00007ffff7b79000 0x00007ffff7c71000 Yes /usr/lib/libm.so.6 0x00007ffff7989000 0x00007ffff7b79000 Yes /usr/lib/libc.so.6 0x00007ffff7fc6000 0x00007ffff7fff000 Yes /usr/lib/ld-linux-x86-64.so.2 0x00007ffff7f99000 0x00007ffff7f9e000 Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.2.so . . There are 5 libraries loaded in linker namespace [[2]] Displaying libraries for linker namespace [[2]]: From To Syms Read Shared Object Library 0x00007ffff7fc6000 0x00007ffff7fff000 Yes /usr/lib/ld-linux-x86-64.so.2 0x00007ffff7fa3000 0x00007ffff7fa8000 Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.1.so 0x00007ffff7f9e000 0x00007ffff7fa3000 Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib-dep.so 0x00007ffff7891000 0x00007ffff7989000 Yes /usr/lib/libm.so.6 0x00007ffff76a1000 0x00007ffff7891000 Yes /usr/lib/libc.so.6 (gdb) info sharedlibrary From To NS Syms Read Shared Object Library 0x00007ffff7fc6000 0x00007ffff7fff000 [[0]] Yes /lib64/ld-linux-x86-64.so.2 0x00007ffff7e94000 0x00007ffff7f8c000 [[0]] Yes /usr/lib/libm.so.6 0x00007ffff7ca4000 0x00007ffff7e94000 [[0]] Yes /usr/lib/libc.so.6 0x00007ffff7fb7000 0x00007ffff7fbc000 [[1]] Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.1.so 0x00007ffff7fb2000 0x00007ffff7fb7000 [[1]] Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib-dep.so 0x00007ffff7b79000 0x00007ffff7c71000 [[1]] Yes /usr/lib/libm.so.6 0x00007ffff7989000 0x00007ffff7b79000 [[1]] Yes /usr/lib/libc.so.6 0x00007ffff7fc6000 0x00007ffff7fff000 [[1]] Yes /usr/lib/ld-linux-x86-64.so.2 0x00007ffff7fad000 0x00007ffff7fb2000 [[0]] Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.1.so 0x00007ffff7fa8000 0x00007ffff7fad000 [[0]] Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib-dep.so 0x00007ffff7fa3000 0x00007ffff7fa8000 [[2]] Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.1.so 0x00007ffff7f9e000 0x00007ffff7fa3000 [[2]] Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib-dep.so 0x00007ffff7891000 0x00007ffff7989000 [[2]] Yes /usr/lib/libm.so.6 0x00007ffff76a1000 0x00007ffff7891000 [[2]] Yes /usr/lib/libc.so.6 0x00007ffff7fc6000 0x00007ffff7fff000 [[1]] Yes /usr/lib/ld-linux-x86-64.so.2 0x00007ffff7f99000 0x00007ffff7f9e000 [[1]] Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.2.so Here is what I would change: - I find that the [[...]] notation used everywhere is heavy and noisy. I understand that this is the (proposed) notation for specifying a namespace id in an expression. But I don't think it's useful to print those brackets everywhere (when it's obvious from the context that the number is a namespace id). I would remove them from the messages and from the tables. - I find these lines a bit too verbose: There are X libraries loaded in linker namespace [[Y]] Displaying libraries for linker namespace [[Y]]: I think they can be condensed to a single line, without loss of information (I think that printing the number of libs in each namespace is not essential, but I don't really mind, so I left it there). - I would add an empty line after the "There are N linker namespaces loaded" message, to visually separate it from the first group. I would also finish that line with a period. - There are two empty lines between each group I think that one empty line is sufficient to do a visual separation. Here's how it looks with this patch: (gdb) info linker-namespaces There are 3 linker namespaces loaded. 5 libraries loaded in linker namespace 0: From To Syms Read Shared Object Library 0x00007ffff7fc6000 0x00007ffff7fff000 Yes /lib64/ld-linux-x86-64.so.2 0x00007ffff7e94000 0x00007ffff7f8c000 Yes /usr/lib/libm.so.6 0x00007ffff7ca4000 0x00007ffff7e94000 Yes /usr/lib/libc.so.6 0x00007ffff7fad000 0x00007ffff7fb2000 Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.1.so 0x00007ffff7fa8000 0x00007ffff7fad000 Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib-dep.so 6 libraries loaded in linker namespace 1: From To Syms Read Shared Object Library 0x00007ffff7fb7000 0x00007ffff7fbc000 Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.1.so 0x00007ffff7fb2000 0x00007ffff7fb7000 Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib-dep.so 0x00007ffff7b79000 0x00007ffff7c71000 Yes /usr/lib/libm.so.6 0x00007ffff7989000 0x00007ffff7b79000 Yes /usr/lib/libc.so.6 0x00007ffff7fc6000 0x00007ffff7fff000 Yes /usr/lib/ld-linux-x86-64.so.2 0x00007ffff7f99000 0x00007ffff7f9e000 Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.2.so 5 libraries loaded in linker namespace 2: From To Syms Read Shared Object Library 0x00007ffff7fc6000 0x00007ffff7fff000 Yes /usr/lib/ld-linux-x86-64.so.2 0x00007ffff7fa3000 0x00007ffff7fa8000 Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.1.so 0x00007ffff7f9e000 0x00007ffff7fa3000 Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib-dep.so 0x00007ffff7891000 0x00007ffff7989000 Yes /usr/lib/libm.so.6 0x00007ffff76a1000 0x00007ffff7891000 Yes /usr/lib/libc.so.6 (gdb) info shared From To Linker NS Syms Read Shared Object Library 0x00007ffff7fc6000 0x00007ffff7fff000 0 Yes /lib64/ld-linux-x86-64.so.2 0x00007ffff7e94000 0x00007ffff7f8c000 0 Yes /usr/lib/libm.so.6 0x00007ffff7ca4000 0x00007ffff7e94000 0 Yes /usr/lib/libc.so.6 0x00007ffff7fb7000 0x00007ffff7fbc000 1 Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.1.so 0x00007ffff7fb2000 0x00007ffff7fb7000 1 Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib-dep.so 0x00007ffff7b79000 0x00007ffff7c71000 1 Yes /usr/lib/libm.so.6 0x00007ffff7989000 0x00007ffff7b79000 1 Yes /usr/lib/libc.so.6 0x00007ffff7fc6000 0x00007ffff7fff000 1 Yes /usr/lib/ld-linux-x86-64.so.2 0x00007ffff7fad000 0x00007ffff7fb2000 0 Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.1.so 0x00007ffff7fa8000 0x00007ffff7fad000 0 Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib-dep.so 0x00007ffff7fa3000 0x00007ffff7fa8000 2 Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.1.so 0x00007ffff7f9e000 0x00007ffff7fa3000 2 Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib-dep.so 0x00007ffff7891000 0x00007ffff7989000 2 Yes /usr/lib/libm.so.6 0x00007ffff76a1000 0x00007ffff7891000 2 Yes /usr/lib/libc.so.6 0x00007ffff7fc6000 0x00007ffff7fff000 1 Yes /usr/lib/ld-linux-x86-64.so.2 0x00007ffff7f99000 0x00007ffff7f9e000 1 Yes /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.mi/mi-dlmopen/dlmopen-lib.2.so Change-Id: Iefad340f7f43a15cff24fc8e1301f91d3d7f0278 Reviewed-By: Guinevere Larsen <guinevere@redhat.com>
-rw-r--r--gdb/solib.c29
-rw-r--r--gdb/testsuite/gdb.base/dlmopen-ns-ids.exp82
-rw-r--r--gdb/testsuite/gdb.base/dlmopen.exp4
-rw-r--r--gdb/testsuite/gdb.mi/mi-dlmopen.exp2
4 files changed, 56 insertions, 61 deletions
diff --git a/gdb/solib.c b/gdb/solib.c
index edcdce5..440562e 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -1042,7 +1042,7 @@ print_solib_list_table (std::vector<const solib *> solib_list,
uiout->table_header (addr_width - 1, ui_left, "from", "From");
uiout->table_header (addr_width - 1, ui_left, "to", "To");
if (print_namespace)
- uiout->table_header (5, ui_left, "namespace", "NS");
+ uiout->table_header (9, ui_left, "namespace", "Linker NS");
uiout->table_header (12 - 1, ui_left, "syms-read", "Syms Read");
uiout->table_header (0, ui_noalign, "name", "Shared Object Library");
@@ -1070,7 +1070,7 @@ print_solib_list_table (std::vector<const solib *> solib_list,
{
try
{
- uiout->field_fmt ("namespace", "[[%d]]", ops->find_solib_ns (*so));
+ uiout->field_fmt ("namespace", "%d", ops->find_solib_ns (*so));
}
catch (const gdb_exception_error &er)
{
@@ -1168,7 +1168,7 @@ info_linker_namespace_command (const char *pattern, int from_tty)
if (pattern == nullptr || pattern[0] == '\0')
{
- uiout->message (_("There are %d linker namespaces loaded\n"),
+ uiout->message (_("There are %d linker namespaces loaded.\n"),
ops->num_active_namespaces ());
int printed = 0;
@@ -1205,27 +1205,26 @@ info_linker_namespace_command (const char *pattern, int from_tty)
(std::make_pair (ns, ops->get_solibs_in_ns (ns)));
}
- bool ns_separator = false;
-
for (const auto &[ns, solibs_to_print] : all_solibs_to_print)
{
- if (ns_separator)
- uiout->message ("\n\n");
- else
- ns_separator = true;
+ uiout->message ("\n");
if (solibs_to_print.size () == 0)
{
- uiout->message (_("Linker namespace [[%d]] is not active.\n"), ns);
+ uiout->message (_("Linker namespace %d is not active.\n"), ns);
/* If we got here, a specific namespace was requested, so there
will only be one vector. We can leave early. */
break;
}
- uiout->message
- (_("There are %zu libraries loaded in linker namespace [[%d]]\n"),
- solibs_to_print.size (), ns);
- uiout->message
- (_("Displaying libraries for linker namespace [[%d]]:\n"), ns);
+
+ if (solibs_to_print.size () == 1)
+ uiout->message
+ (_("1 library loaded in linker namespace %d:\n"), ns);
+ else
+ uiout->message
+ (_("%zu libraries loaded in linker namespace %d:\n"),
+ solibs_to_print.size (), ns);
+
print_solib_list_table (solibs_to_print, false);
}
diff --git a/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp b/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp
index e23edbf..eb12dad 100644
--- a/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp
+++ b/gdb/testsuite/gdb.base/dlmopen-ns-ids.exp
@@ -44,10 +44,10 @@ proc get_first_so_ns {} {
set ns -1
set lib_regexp [string_to_regexp ${::binfile_lib}]
gdb_test_multiple "info sharedlibrary $::so_name" "get SO namespace" -lbl {
- -re "\r\nFrom\\s+To\\s+\(NS\\s+\)?Syms\\s+Read\\s+Shared Object Library(?=\r\n)" {
+ -re "\r\nFrom\\s+To\\s+\(Linker NS\\s+\)?Syms\\s+Read\\s+Shared Object Library(?=\r\n)" {
exp_continue
}
- -re "\r\n$::hex\\s+$::hex\\s+\\\[\\\[($::decimal)\\\]\\\]\\s+\[^\r\n]+${lib_regexp}(?=\r\n)" {
+ -re "\r\n$::hex\\s+$::hex\\s+($::decimal)\\s+\[^\r\n]+${lib_regexp}(?=\r\n)" {
if {$ns == -1} {
set ns $expect_out(1,string)
}
@@ -78,7 +78,7 @@ proc test_info_shared {} {
# Next, test that we *do* print a namespace column after loading SOs.
gdb_test "info sharedlibrary" \
- "From\\s+To\\s+NS\\s+Syms\\s+Read\\s+Shared Object Library.*" \
+ "From\\s+To\\s+Linker NS\\s+Syms\\s+Read\\s+Shared Object Library.*" \
"after loading everything"
gdb_assert {[get_first_so_ns] == 1} "before closing any library"
@@ -188,50 +188,45 @@ proc test_info_linker_namespaces {} {
# First, test printing a single namespace, and ensure all of
# them are correct, using both syntaxes.
- set found_all_libs false
- gdb_test_multiple "info linker-namespaces \[\[0\]\]" "print namespace 0" -lbl {
- -re "^\r\nThere are ($::decimal) libraries loaded in linker namespace \\\[\\\[0\\\]\\\]" {
- # Some systems may add libc and libm to every loaded namespace,
- # others may load only one or neither, because the SO doesn't
- # actually use either library. The best we can do is check if
- # we found the dynamic linker, and up to 2 more libraries.
- set libs $expect_out(1,string)
- set found_all_libs [expr $libs - 1 <= 2]
- exp_continue
- }
- -re "^\r\n$::gdb_prompt $" {
- gdb_assert $found_all_libs "the correct number of libraries was reported"
- }
- -re "(^\r\n)?\[^\r\n\]+(?=\r\n)" {
- exp_continue
+ set n_libraries 999
+
+ gdb_test_multiple "info linker-namespaces \[\[0\]\]" "print namespace 0" {
+ -re -wrap "($::decimal) librar(?:y|ies) loaded in linker namespace 0:.*" {
+ set n_libraries $expect_out(1,string)
}
}
+
+ # Some systems may add libc and libm to every loaded namespace,
+ # others may load only one or neither, because the SO doesn't
+ # actually use either library. The best we can do is check if
+ # we found the dynamic linker, and up to 2 more libraries.
+ gdb_assert {$n_libraries <= 3} "the correct number of libraries was reported"
+
+ set binfile_lib_re [string_to_regexp $::binfile_lib]
+ puts $binfile_lib_re
+
foreach_with_prefix ns {1 2 3} {
set found_test_so false
- set found_all_libs false
- gdb_test_multiple "info linker-namespaces $ns" "print namespace $ns" -lbl {
- -re "^\r\nThere are ($::decimal) libraries loaded in linker namespace \\\[\\\[$ns\\\]\\\]" {
- set libs $expect_out(1,string)
- # Some systems may add libc and libm to every loaded namespace,
- # others may load only one or neither, because the SO doesn't
- # actually use either library. The best we can do is check if
- # we found the dynamic linker, the test SO, and maybe up to 2
- # more libraries.
- set found_all_libs [expr $libs - 2 <= 2]
+ set n_libraries 999
+
+ gdb_test_multiple "info linker-namespaces $ns" "print namespace $ns" {
+ -re ".*($::decimal) librar(?:y|ies) loaded in linker namespace $ns:\r\n" {
+ set n_libraries $expect_out(1,string)
exp_continue
}
- -re "^\r\n\[^\r\n\]+${::binfile_lib}\[^\r\n\]*(?=\r\n)" {
+
+ -re -wrap "${binfile_lib_re}.*" {
set found_test_so true
- exp_continue
- }
- -re "^\r\n$::gdb_prompt $" {
- gdb_assert $found_test_so "this testfle's SO was reported"
- gdb_assert $found_all_libs "the correct number of libraries was reported"
- }
- -re "(^\r\n)?\[^\r\n\]+(?=\r\n)" {
- exp_continue
}
}
+
+ # Some systems may add libc and libm to every loaded namespace,
+ # others may load only one or neither, because the SO doesn't
+ # actually use either library. The best we can do is check if
+ # we found the dynamic linker, the test SO, and maybe up to 2
+ # more libraries.
+ gdb_assert {$n_libraries <= 4} "the correct number of libraries was reported"
+ gdb_assert {$found_test_so} "this testfile's SO was reported"
}
# These patterns are simpler, and purposefully glob multiple lines.
@@ -239,14 +234,15 @@ proc test_info_linker_namespaces {} {
# without worrying about the libraries printed, since that was tested
# above.
gdb_test "info linker-namespaces" \
- [multi_line "There are 4 linker namespaces loaded" \
- "There are $::decimal libraries loaded in linker namespace ..0.." \
+ [multi_line "There are 4 linker namespaces loaded\\." \
+ "" \
+ "$::decimal librar(y|ies) loaded in linker namespace 0:" \
".*" \
- "There are $::decimal libraries loaded in linker namespace ..1.." \
+ "$::decimal librar(y|ies) loaded in linker namespace 1:" \
".*" \
- "There are $::decimal libraries loaded in linker namespace ..2.." \
+ "$::decimal librar(y|ies) loaded in linker namespace 2:" \
".*" \
- "There are $::decimal libraries loaded in linker namespace ..3.." \
+ "$::decimal librar(y|ies) loaded in linker namespace 3:" \
".*" ] "print namespaces with no argument"
}
diff --git a/gdb/testsuite/gdb.base/dlmopen.exp b/gdb/testsuite/gdb.base/dlmopen.exp
index cdc4910..54fb4c4 100644
--- a/gdb/testsuite/gdb.base/dlmopen.exp
+++ b/gdb/testsuite/gdb.base/dlmopen.exp
@@ -116,7 +116,7 @@ proc check_dso_count { dso num } {
set count 0
gdb_test_multiple "info shared" "info shared" {
- -re "$hex $hex \(\[\[$::decimal\]\]\\s+\)\?Yes \[^\r\n\]*$dso\r\n" {
+ -re "$hex $hex \($::decimal\\s+\)\?Yes \[^\r\n\]*$dso\r\n" {
# use longer form so debug remote does not interfere
set count [expr $count + 1]
exp_continue
@@ -243,7 +243,7 @@ proc get_dyld_info {} {
set dyld_count 0
set dyld_start_addr ""
gdb_test_multiple "info sharedlibrary" "" {
- -re "From\\s+To\\s+\(NS\\s+\)?Syms\\s+Read\\s+Shared Object Library\r\n" {
+ -re "From\\s+To\\s+\(Linker NS\\s+\)?Syms\\s+Read\\s+Shared Object Library\r\n" {
exp_continue
}
-re "^($::hex)\\s+$::hex\\s+\(\#$::decimal\\s+\)?\[^/\]+(/\[^\r\n\]+)\r\n" {
diff --git a/gdb/testsuite/gdb.mi/mi-dlmopen.exp b/gdb/testsuite/gdb.mi/mi-dlmopen.exp
index fa7e373..936027f 100644
--- a/gdb/testsuite/gdb.mi/mi-dlmopen.exp
+++ b/gdb/testsuite/gdb.mi/mi-dlmopen.exp
@@ -91,7 +91,7 @@ proc get_dyld_info {} {
set dyld_count 0
set dyld_start_addr ""
gdb_test_multiple "info sharedlibrary" "" {
- -re "~\"From\\s+To(\\s+NS)?\\s+Syms\\s+Read\\s+Shared Object Library\\\\n\"\r\n" {
+ -re "~\"From\\s+To(\\s+Linker NS)?\\s+Syms\\s+Read\\s+Shared Object Library\\\\n\"\r\n" {
exp_continue
}
-re "^~\"($::hex)\\s+${::hex}(\\s+$::decimal)?\\s+\[^/\]+(/\[^\r\n\]+)\\\\n\"\r\n" {