diff --git a/binutils/strings.c b/binutils/strings.c
index 3444fbc7222..d4abeb0cdbb 100644
--- a/binutils/strings.c
+++ b/binutils/strings.c
@@ -26,6 +26,10 @@
--data
-d Scan only the initialized data section(s) of object files.
+ --section=<section>
+ -S <section> Scan only the specific section(s)
+ --kernel
+ -k Scan only linux-kernel KERN_SOH strings
--print-file-name
-f Print the name of the file before each string.
@@ -108,6 +112,14 @@ static bfd_boolean print_filenames;
/* TRUE means for object files scan only the data section. */
static bfd_boolean datasection_only;
+/* TRUE means for object files scan only the specified sections. */
+static bfd_boolean specified_sections_only;
+static int specified_sections_count;
+static char **specified_sections;
+
+/* TRUE means scan only linux-kernel printk strings with KERN_SOH. */
+static bfd_boolean linux_kernel_soh;
+
/* The BFD object file format. */
static char *target;
@@ -122,6 +134,8 @@ static struct option long_options[] =
{
{"all", no_argument, NULL, 'a'},
{"data", no_argument, NULL, 'd'},
+ {"section", required_argument, NULL, 'S'},
+ {"kernel", no_argument, NULL, 'k'},
{"print-file-name", no_argument, NULL, 'f'},
{"bytes", required_argument, NULL, 'n'},
{"radix", required_argument, NULL, 't'},@@ -173,7 +187,7 @@ main (int argc, char **argv)
encoding = 's';
output_separator = NULL;
- while ((optc = getopt_long (argc, argv, "adfhHn:wot:e:T:s:Vv0123456789",
+ while ((optc = getopt_long (argc, argv, "adS:s:kfhHn:wot:e:T:s:Vv0123456789",
long_options, (int *) 0)) != EOF)
{
switch (optc)@@ -186,6 +200,17 @@ main (int argc, char **argv)
datasection_only = TRUE;
break;
+ case 'S':
+ specified_sections_only = TRUE;
+ specified_sections = xrealloc(specified_sections,
+ (specified_sections_count + 1) * sizeof(const char *));
+ specified_sections[specified_sections_count++] = optarg;
+ break;
+
+ case 'k':
+ linux_kernel_soh = TRUE;
+ break;
+
case 'f':
print_filenames = TRUE;
break;
@@ -318,6 +343,19 @@ main (int argc, char **argv)
return (exit_status);
}
+static bfd_boolean
+section_is_specified_section (asection *sect)
+{
+ int i;
+ for (i = 0; i < specified_sections_count; i++)
+ {
+ if (strcmp(specified_sections[i], sect->name) == 0) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
/* Scan section SECT of the file ABFD, whose printable name is
FILENAME. If it contains initialized data set GOT_A_SECTION and
print the strings in it. */@@ -329,7 +367,9 @@ strings_a_section (bfd *abfd, asection *sect, const char *filename,
bfd_size_type sectsize;
bfd_byte *mem;
- if ((sect->flags & DATA_FLAGS) != DATA_FLAGS)
+ if (specified_sections_only && !section_is_specified_section (sect))
+ return;
+ if (datasection_only && ((sect->flags & DATA_FLAGS) != DATA_FLAGS))
return;
sectsize = bfd_section_size (sect);@@ -417,7 +457,7 @@ strings_file (char *file)
try to open it as an object file and only look at
initialized data sections. If that fails, fall back to the
whole file. */
- if (!datasection_only || !strings_object_file (file))
+ if (!(datasection_only || specified_sections_only) || !strings_object_file (file))
{
FILE *stream;
@@ -571,6 +611,7 @@ print_strings (const char *filename, FILE *stream, file_ptr address,
int stop_point, int magiccount, char *magic)
{
char *buf = (char *) xmalloc (sizeof (char) * (string_min + 1));
+ int is_kernel = 0;
while (1)
{@@ -594,6 +635,7 @@ print_strings (const char *filename, FILE *stream, file_ptr address,
if (! STRING_ISGRAPHIC (c))
{
+ is_kernel = c == 1;
/* Found a non-graphic. Try again starting with next byte. */
unget_part_char (c, &address, &magiccount, &magic);
goto tryline;@@ -601,6 +643,22 @@ print_strings (const char *filename, FILE *stream, file_ptr address,
buf[i] = c;
}
+ if ((linux_kernel_soh && !is_kernel) ||
+ (linux_kernel_soh && !strchr("01234567cd", buf[0])))
+ {
+ while (1) {
+ c = get_char (stream, &address, &magiccount, &magic);
+ if (c == EOF)
+ return;
+ if (! STRING_ISGRAPHIC (c))
+ {
+ unget_part_char (c, &address, &magiccount, &magic);
+ break;
+ }
+ }
+ goto tryline;
+ }
+
/* We found a run of `string_min' graphic characters. Print up
to the next non-graphic character. */
@@ -668,8 +726,11 @@ print_strings (const char *filename, FILE *stream, file_ptr address,
break;
}
- buf[i] = '\0';
- fputs (buf, stdout);
+ if (!linux_kernel_soh || is_kernel)
+ {
+ buf[i] = '\0';
+ fputs (buf, stdout);
+ }
while (1)
{@@ -681,13 +742,20 @@ print_strings (const char *filename, FILE *stream, file_ptr address,
unget_part_char (c, &address, &magiccount, &magic);
break;
}
- putchar (c);
+ if (!linux_kernel_soh || is_kernel)
+ {
+ putchar (c);
+ }
}
- if (output_separator)
- fputs (output_separator, stdout);
- else
- putchar ('\n');
+ if (!linux_kernel_soh || is_kernel)
+ {
+ if (output_separator)
+ fputs (output_separator, stdout);
+ else
+ putchar ('\n');
+ }
+ is_kernel = 0;
}
free (buf);
}@@ -702,13 +770,11 @@ usage (FILE *stream, int status)
if (DEFAULT_STRINGS_ALL)
fprintf (stream, _("\
-a - --all Scan the entire file, not just the data section [default]\n\
- -d --data Only scan the data sections in the file\n"));
- else
- fprintf (stream, _("\
+ -d --data Only scan the data sections in the file\n\
+ -S --section=[section] Only scan the specific sections\n\
+ -k --kernel Only scan for linux-kernel strings with KERN_SOH\n\
-a - --all Scan the entire file, not just the data section\n\
- -d --data Only scan the data sections in the file [default]\n"));
-
- fprintf (stream, _("\
+ -d --data Only scan the data sections in the file [default]\n\
-f --print-file-name Print the name of the file before each string\n\
-n --bytes=[number] Locate & print any NUL-terminated sequence of at\n\
-<number> least [number] characters (default 4).\n\