[PATCH 2/2] iasl: capture output from stderr to catch iasl fatal errors
Colin King
colin.king at canonical.com
Thu Oct 3 10:36:04 UTC 2013
From: Colin Ian King <colin.king at canonical.com>
ACPICA commit 7bbc5f141be1b15e232da253d331dda6de4d8b1c now
makes iasl abort immediately on serious unrecoverable parse errors
and emits an error message on stderr. We need to capture this and
pass it up to the syntaxcheck test to report back that iasl has
aborted early. The upside is that syntaxcheck now does not report
tens of parser errors.
Signed-off-by: Colin Ian King <colin.king at canonical.com>
---
src/acpi/syntaxcheck/syntaxcheck.c | 31 ++++++--
src/acpica/source/compiler/fwts_iasl_interface.c | 98 +++++++++++++++++-------
src/acpica/source/compiler/fwts_iasl_interface.h | 2 +-
src/lib/include/fwts_iasl.h | 5 +-
src/lib/src/fwts_iasl.c | 18 +++--
5 files changed, 109 insertions(+), 45 deletions(-)
diff --git a/src/acpi/syntaxcheck/syntaxcheck.c b/src/acpi/syntaxcheck/syntaxcheck.c
index 9bd6711..749bd1b 100644
--- a/src/acpi/syntaxcheck/syntaxcheck.c
+++ b/src/acpi/syntaxcheck/syntaxcheck.c
@@ -441,8 +441,7 @@ static int syntaxcheck_table(fwts_framework *fw, char *tablename, int which)
int warnings = 0;
int remarks = 0;
fwts_acpi_table_info *table;
- fwts_list* iasl_errors;
- fwts_list* iasl_disassembly;
+ fwts_list *iasl_stdout, *iasl_stderr, *iasl_disassembly;
if (fwts_acpi_find_table(fw, tablename, which, &table) != FWTS_OK) {
fwts_aborted(fw, "Cannot load ACPI table %s.", tablename);
@@ -453,7 +452,7 @@ static int syntaxcheck_table(fwts_framework *fw, char *tablename, int which)
return FWTS_NO_TABLE; /* Table does not exist */
if (fwts_iasl_reassemble(fw, table->data, table->length,
- &iasl_disassembly, &iasl_errors) != FWTS_OK) {
+ &iasl_disassembly, &iasl_stdout, &iasl_stderr) != FWTS_OK) {
fwts_aborted(fw, "Cannot re-assasemble with iasl.");
return FWTS_ERROR;
}
@@ -462,9 +461,9 @@ static int syntaxcheck_table(fwts_framework *fw, char *tablename, int which)
fwts_log_info(fw, "Checking ACPI table %s (#%d)", tablename, which);
fwts_log_nl(fw);
- if (iasl_errors) {
+ if (iasl_stdout) {
/* Scan error text from assembly */
- fwts_list_foreach(item, iasl_errors) {
+ fwts_list_foreach(item, iasl_stdout) {
int num;
char ch;
char *line = fwts_text_list_text(item);
@@ -554,8 +553,28 @@ static int syntaxcheck_table(fwts_framework *fw, char *tablename, int which)
}
}
}
+
+ /*
+ * Did iasl emit any errors that we need to check?
+ */
+ if (iasl_stderr) {
+ fwts_list_foreach(item, iasl_stderr) {
+ char *line = fwts_text_list_text(item);
+ if (strstr(line, "Compiler aborting due to parser-detected syntax error")) {
+ fwts_failed(fw, LOG_LEVEL_HIGH, "SyntaxCheckIASLCompilerAborted",
+ "Compilation aborted early due to a parser detected syntax error.");
+ fwts_advice(fw,
+ "Some subsequent errors may not be detected because the "
+ "compiler had to terminate prematurely. If the compiler did not "
+ "abort early then potentially correct code may parse incorrectly "
+ "producing some or many false positive errors.");
+ }
+ }
+ }
+
fwts_text_list_free(iasl_disassembly);
- fwts_text_list_free(iasl_errors);
+ fwts_text_list_free(iasl_stdout);
+ fwts_text_list_free(iasl_stderr);
if (errors + warnings + remarks > 0)
fwts_log_info(fw, "Table %s (%d) reassembly: Found %d errors, %d warnings, %d remarks.",
diff --git a/src/acpica/source/compiler/fwts_iasl_interface.c b/src/acpica/source/compiler/fwts_iasl_interface.c
index 49278ec..607dec3 100644
--- a/src/acpica/source/compiler/fwts_iasl_interface.c
+++ b/src/acpica/source/compiler/fwts_iasl_interface.c
@@ -19,6 +19,8 @@
#define _DECLARE_GLOBALS
+#include <unistd.h>
+#include <stdbool.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -27,6 +29,10 @@
#include "aslcompiler.h"
#include "acapps.h"
+/*
+ * init_asl_core()
+ * initialize iasl
+ */
static void init_asl_core(void)
{
int i;
@@ -49,6 +55,10 @@ static void init_asl_core(void)
UtExpandLineBuffers();
}
+/*
+ * fwts_iasl_disassemble_aml()
+ * invoke iasl to disassemble AML
+ */
int fwts_iasl_disassemble_aml(const char *aml, const char *outputfile)
{
pid_t pid;
@@ -63,6 +73,8 @@ int fwts_iasl_disassemble_aml(const char *aml, const char *outputfile)
init_asl_core();
/* Setup ACPICA disassembler globals */
+ Gbl_WarningLevel = ASL_WARNING3;
+ Gbl_IgnoreErrors = TRUE;
Gbl_DisasmFlag = TRUE;
Gbl_DoCompile = FALSE;
Gbl_OutputFilenamePrefix = (char*)outputfile;
@@ -82,38 +94,70 @@ int fwts_iasl_disassemble_aml(const char *aml, const char *outputfile)
return 0;
}
-int fwts_iasl_assemble_aml(const char *source, char **output)
+/*
+ * fwts_iasl_read_output()
+ * consume output from iasl.
+ */
+static int fwts_iasl_read_output(const int fd, char **data, size_t *len, bool *eof)
{
- int pipefds[2];
- int status;
- int ret = 0;
- size_t len = 0;
+ char buffer[8192];
ssize_t n;
+
+ if (*eof)
+ return 0;
+
+ while ((n = read(fd, buffer, sizeof(buffer))) > 0) {
+ if ((*data = realloc(*data, *len + n + 1)) == NULL)
+ return -1;
+ memcpy(*data + *len, buffer, n);
+ *len += n;
+ (*data)[*len] = '\0';
+ }
+ if (n <= 0)
+ *eof = true;
+ return 0;
+}
+
+/*
+ * fwts_iasl_assemble_aml()
+ * invoke iasl and assemble some source, stdout into
+ * stdout_output, stderr into stderr_output
+ */
+int fwts_iasl_assemble_aml(const char *source, char **stdout_output, char **stderr_output)
+{
+ int stdout_fds[2], stderr_fds[2];
+ int status, ret = 0;
+ size_t stdout_len = 0, stderr_len = 0;
pid_t pid;
- char *data = NULL;
- char buffer[8192];
+ bool stdout_eof = false, stderr_eof = false;
- if (pipe(pipefds) < 0)
+ if (pipe(stdout_fds) < 0)
+ return -1;
+ if (pipe(stderr_fds) < 0)
return -1;
pid = fork();
switch (pid) {
case -1:
- (void)close(pipefds[0]);
- (void)close(pipefds[1]);
+ (void)close(stdout_fds[0]);
+ (void)close(stdout_fds[1]);
+ (void)close(stderr_fds[0]);
+ (void)close(stderr_fds[1]);
return -1;
case 0:
/* Child */
init_asl_core();
/* stdout to be redirected down the writer end of pipe */
- if (pipefds[1] != STDOUT_FILENO) {
- if (dup2(pipefds[1], STDOUT_FILENO) < 0) {
+ if (stdout_fds[1] != STDOUT_FILENO)
+ if (dup2(stdout_fds[1], STDOUT_FILENO) < 0)
+ _exit(EXIT_FAILURE);
+ if (stderr_fds[1] != STDERR_FILENO)
+ if (dup2(stderr_fds[1], STDERR_FILENO) < 0)
_exit(EXIT_FAILURE);
- }
- }
/* Close reader end */
- (void)close(pipefds[0]);
+ (void)close(stdout_fds[0]);
+ (void)close(stderr_fds[0]);
/* Setup ACPICA compiler globals */
Gbl_DisasmFlag = FALSE;
@@ -128,32 +172,28 @@ int fwts_iasl_assemble_aml(const char *source, char **output)
* We need to flush buffered I/O on IASL stdout
* before we exit
*/
- fflush(stdout);
+ (void)fflush(stdout);
+ (void)fflush(stderr);
_exit(0);
break;
default:
/* Parent */
-
/* Close writer end */
- (void)close(pipefds[1]);
+ (void)close(stdout_fds[1]);
+ (void)close(stderr_fds[1]);
- /* Gather output from IASL */
- while ((n = read(pipefds[0], buffer, sizeof(buffer))) > 0) {
- data = realloc(data, len + n + 1);
- if (data == NULL) {
- ret = -1;
+ while (!stdout_eof && !stderr_eof) {
+ if (fwts_iasl_read_output(stdout_fds[0], stdout_output, &stdout_len, &stdout_eof) < 0)
+ break;
+ if (fwts_iasl_read_output(stderr_fds[0], stderr_output, &stderr_len, &stderr_eof) < 0)
break;
- }
- memcpy(data + len, buffer, n);
- len += n;
- data[len] = '\0';
}
(void)waitpid(pid, &status, WUNTRACED | WCONTINUED);
- (void)close(pipefds[0]);
+ (void)close(stdout_fds[0]);
+ (void)close(stderr_fds[0]);
break;
}
- *output = data;
return ret;
}
diff --git a/src/acpica/source/compiler/fwts_iasl_interface.h b/src/acpica/source/compiler/fwts_iasl_interface.h
index f88ccd8..71675d3 100644
--- a/src/acpica/source/compiler/fwts_iasl_interface.h
+++ b/src/acpica/source/compiler/fwts_iasl_interface.h
@@ -21,6 +21,6 @@
#define __FWTS_IASL_INTERFACE__
int fwts_iasl_disassemble_aml(const char *aml, const char *outputfile);
-int fwts_iasl_assemble_aml(const char *source, char **output);
+int fwts_iasl_assemble_aml(const char *source, char **stdout_output, char **stderr_output);
#endif
diff --git a/src/lib/include/fwts_iasl.h b/src/lib/include/fwts_iasl.h
index 58ffffa..78b2936 100644
--- a/src/lib/include/fwts_iasl.h
+++ b/src/lib/include/fwts_iasl.h
@@ -24,7 +24,7 @@
int fwts_iasl_disassemble_all_to_file(fwts_framework *fw);
-int fwts_iasl_disassemble(fwts_framework *fw,
+int fwts_iasl_disassemble(fwts_framework *fw,
const char *table,
const int which,
fwts_list **ias_output);
@@ -33,6 +33,7 @@ int fwts_iasl_reassemble(fwts_framework *fw,
const uint8_t *data,
const int len,
fwts_list **iasl_disassembly,
- fwts_list **iasl_errors);
+ fwts_list **iasl_stdout,
+ fwts_list **iasl_stderr);
#endif
diff --git a/src/lib/src/fwts_iasl.c b/src/lib/src/fwts_iasl.c
index 5058c1e..27eeef0 100644
--- a/src/lib/src/fwts_iasl.c
+++ b/src/lib/src/fwts_iasl.c
@@ -172,14 +172,17 @@ int fwts_iasl_reassemble(fwts_framework *fw,
const uint8_t *data,
const int len,
fwts_list **iasl_disassembly,
- fwts_list **iasl_errors)
+ fwts_list **iasl_stdout,
+ fwts_list **iasl_stderr)
{
char tmpfile[PATH_MAX];
char amlfile[PATH_MAX];
- char *output_text = NULL;
+ char *stdout_output = NULL, *stderr_output = NULL;
int pid = getpid();
- if ((iasl_disassembly == NULL) || (iasl_errors == NULL))
+ if ((iasl_disassembly == NULL) ||
+ (iasl_stdout == NULL) ||
+ (iasl_stderr == NULL))
return FWTS_ERROR;
fwts_acpcia_set_fwts_framework(fw);
@@ -205,10 +208,10 @@ int fwts_iasl_reassemble(fwts_framework *fw,
/* Now we have a disassembled source in tmpfile, so let's assemble it */
- if (fwts_iasl_assemble_aml(tmpfile, &output_text) < 0) {
+ if (fwts_iasl_assemble_aml(tmpfile, &stdout_output, &stderr_output) < 0) {
(void)unlink(amlfile);
(void)unlink(tmpfile);
- free(output_text);
+ free(stdout_output);
return FWTS_ERROR;
}
@@ -220,8 +223,9 @@ int fwts_iasl_reassemble(fwts_framework *fw,
snprintf(tmpfile, sizeof(tmpfile), "/tmp/fwts_iasl_%d.aml", pid);
(void)unlink(tmpfile);
- *iasl_errors = fwts_list_from_text(output_text);
- free(output_text);
+ *iasl_stdout = fwts_list_from_text(stdout_output);
+ *iasl_stderr = fwts_list_from_text(stderr_output);
+ free(stdout_output);
return FWTS_OK;
}
--
1.8.3.2
More information about the fwts-devel
mailing list