This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Commit: Add support for a temporary input line pointer in gas/read.c
- From: Nick Clifton <nickc at redhat dot com>
- To: binutils at sourceware dot org
- Date: Thu, 12 Jan 2017 14:55:41 +0000
- Subject: Commit: Add support for a temporary input line pointer in gas/read.c
- Authentication-results: sourceware.org; auth=none
Hi Guys,
I am checking in the attached patch to fix a internal assembler when
gas is generating STABS output and it encounters a parsing error. The
problem was that the stabs functions would call the parsers in
gas/read.c with a temporary input line pointer, but without setting
the limit for this pointer. So if a parsing error occurred, the
assembler might attempt to read beyond the end of the temporary buffer
which causes all kinds of problems.
The patch solves the problem by adding a new function to gas/read.c to
set a temporary input line pointer, and update the buffer_limit
variable at the same time. In this way the functions in stabs.c can
safely create and use their temporary input line buffers.
There are probably other places in gas where a temporary input line
pointer is used and these functions would be helpful, but I have not
investigated this yet.
Cheers
Nick
gas/ChangeLog
2017-01-12 Nick Clifton <nickc@redhat.com>
* read.c (temp_ilp): New function. Installs a temporary input
line pointer.
(restore_ilp): New function. Restores the original input line
pointer.
* read.h (temp_ilp): Prototype.
(restore_ilp): Prototype.
* stabs.c (dot_func_p): Use bfd_boolean type.
(generate_asm_file): Use temp_ilp and restore_ilp.
(stabs_generate_asm_lineno): Likewise.
(stabs_generate_asm_endfunc): Likewise.
diff --git a/gas/read.c b/gas/read.c
index 3669b28..4ca8b01 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -6333,3 +6333,47 @@ find_end_of_line (char *s, int mri_string)
{
return _find_end_of_line (s, mri_string, 0, 0);
}
+
+static char *saved_ilp = NULL;
+static char *saved_limit;
+
+/* Use BUF as a temporary input pointer for calling other functions in this
+ file. BUF must be a C string, so that its end can be found by strlen.
+ Also sets the buffer_limit variable (local to this file) so that buffer
+ overruns should not occur. Saves the current input line pointer so that
+ it can be restored by calling restore_ilp().
+
+ Does not support recursion.
+
+ FIXME: This function is currently only used by stabs.c but that
+ should be extended to other files in the gas source directory. */
+
+void
+temp_ilp (char *buf)
+{
+ gas_assert (saved_ilp == NULL);
+ gas_assert (buf != NULL);
+
+ saved_ilp = input_line_pointer;
+ saved_limit = buffer_limit;
+ /* Prevent the assert in restore_ilp from triggering if
+ the input_line_pointer has not yet been initialised. */
+ if (saved_ilp == NULL)
+ saved_limit = saved_ilp = (char *) "";
+
+ input_line_pointer = buf;
+ buffer_limit = buf + strlen (buf);
+}
+
+/* Restore a saved input line pointer. */
+
+void
+restore_ilp (void)
+{
+ gas_assert (saved_ilp != NULL);
+
+ input_line_pointer = saved_ilp;
+ buffer_limit = saved_limit;
+
+ saved_ilp = NULL;
+}
diff --git a/gas/read.h b/gas/read.h
index f1ccf92..e83118f 100644
--- a/gas/read.h
+++ b/gas/read.h
@@ -213,3 +213,5 @@ extern void s_xstab (int what);
extern void s_rva (int);
extern void s_incbin (int);
extern void s_weakref (int);
+extern void temp_ilp (char *);
+extern void restore_ilp (void);
diff --git a/gas/stabs.c b/gas/stabs.c
index 49fc09b..f9127f0 100644
--- a/gas/stabs.c
+++ b/gas/stabs.c
@@ -46,13 +46,13 @@ static void generate_asm_file (int, const char *);
#define STAB_STRING_SECTION_NAME ".stabstr"
#endif
-/* Non-zero if we're in the middle of a .func function, in which case
+/* True if we're in the middle of a .func function, in which case
stabs_generate_asm_lineno emits function relative line number stabs.
Otherwise it emits line number stabs with absolute addresses. Note that
both cases only apply to assembler code assembled with -gstabs. */
-static int in_dot_func_p;
+static bfd_boolean in_dot_func_p = FALSE;
-/* Label at start of current function if in_dot_func_p != 0. */
+/* Label at start of current function if in_dot_func_p != FALSE. */
static const char *current_function_label;
/*
@@ -510,7 +510,6 @@ generate_asm_file (int type, const char *file)
{
static char *last_file;
static int label_count;
- char *hold;
char sym[30];
char *buf;
const char *tmp = file;
@@ -525,8 +524,6 @@ generate_asm_file (int type, const char *file)
generate a string and then parse it again. That lets us use the
existing stabs hook, which expect to see a string, rather than
inventing new ones. */
- hold = input_line_pointer;
-
sprintf (sym, "%sF%d", FAKE_LABEL_NAME, label_count);
++label_count;
@@ -556,8 +553,10 @@ generate_asm_file (int type, const char *file)
sprintf (bufp, "\",%d,0,0,%s\n", type, sym);
- input_line_pointer = buf;
+ temp_ilp (buf);
s_stab ('s');
+ restore_ilp ();
+
colon (sym);
if (last_file != NULL)
@@ -565,8 +564,6 @@ generate_asm_file (int type, const char *file)
last_file = xstrdup (file);
free (buf);
-
- input_line_pointer = hold;
}
/* Generate stabs debugging information for the current line. This is
@@ -576,7 +573,6 @@ void
stabs_generate_asm_lineno (void)
{
static int label_count;
- char *hold;
const char *file;
unsigned int lineno;
char *buf;
@@ -590,8 +586,6 @@ stabs_generate_asm_lineno (void)
existing stabs hook, which expect to see a string, rather than
inventing new ones. */
- hold = input_line_pointer;
-
file = as_where (&lineno);
/* Don't emit sequences of stabs for the same line. */
@@ -638,11 +632,13 @@ stabs_generate_asm_lineno (void)
buf = XNEWVEC (char, 100);
sprintf (buf, "%d,0,%d,%s\n", N_SLINE, lineno, sym);
}
- input_line_pointer = buf;
+
+ temp_ilp (buf);
s_stab ('n');
+ restore_ilp ();
+
colon (sym);
- input_line_pointer = hold;
outputting_stabs_line_debug = 0;
free (buf);
}
@@ -653,29 +649,30 @@ stabs_generate_asm_lineno (void)
void
stabs_generate_asm_func (const char *funcname, const char *startlabname)
{
- static int void_emitted_p;
- char *hold = input_line_pointer;
+ static bfd_boolean void_emitted_p = FALSE;
char *buf;
unsigned int lineno;
if (! void_emitted_p)
{
- input_line_pointer = (char *) "\"void:t1=1\",128,0,0,0";
+ temp_ilp ((char *) "\"void:t1=1\",128,0,0,0");
s_stab ('s');
- void_emitted_p = 1;
+ restore_ilp ();
+ void_emitted_p = TRUE;
}
as_where (&lineno);
if (asprintf (&buf, "\"%s:F1\",%d,0,%d,%s",
funcname, N_FUN, lineno + 1, startlabname) == -1)
as_fatal ("%s", xstrerror (errno));
- input_line_pointer = buf;
+
+ temp_ilp (buf);
s_stab ('s');
+ restore_ilp ();
free (buf);
- input_line_pointer = hold;
current_function_label = xstrdup (startlabname);
- in_dot_func_p = 1;
+ in_dot_func_p = TRUE;
}
/* Emit a stab to record the end of a function. */
@@ -685,7 +682,6 @@ stabs_generate_asm_endfunc (const char *funcname ATTRIBUTE_UNUSED,
const char *startlabname)
{
static int label_count;
- char *hold = input_line_pointer;
char *buf;
char sym[30];
@@ -695,11 +691,12 @@ stabs_generate_asm_endfunc (const char *funcname ATTRIBUTE_UNUSED,
if (asprintf (&buf, "\"\",%d,0,0,%s-%s", N_FUN, sym, startlabname) == -1)
as_fatal ("%s", xstrerror (errno));
- input_line_pointer = buf;
+
+ temp_ilp (buf);
s_stab ('s');
+ restore_ilp ();
free (buf);
- input_line_pointer = hold;
- in_dot_func_p = 0;
+ in_dot_func_p = FALSE;
current_function_label = NULL;
}