summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Rowe <erowe@google.com>2014-08-15 17:03:28 -0700
committerEric Rowe <erowe@google.com>2014-08-15 17:03:28 -0700
commite337a91a147162fbad603c05c5ddffd12bff6f7d (patch)
tree0965eeeaed3f10986a20294ad50cd297737faca4
parentdf2e25b0b50559b3d293a15a0714d41608eca305 (diff)
downloadloganalysis-e337a91a147162fbad603c05c5ddffd12bff6f7d.tar.gz
Update boot reason parsing for with 3.10 kernel
Also, bring kernel log parser in line with APR and only record first kernel reset. Bug: 14829888 Change-Id: Ice5db062b3fc8ece774afc8e284f1a276aa52d43
-rw-r--r--src/com/android/loganalysis/item/BugreportItem.java22
-rw-r--r--src/com/android/loganalysis/item/KernelLogItem.java7
-rw-r--r--src/com/android/loganalysis/parser/BugreportParser.java37
-rw-r--r--src/com/android/loganalysis/parser/KernelLogParser.java12
-rw-r--r--tests/src/com/android/loganalysis/parser/BugreportParserTest.java79
-rw-r--r--tests/src/com/android/loganalysis/parser/KernelLogParserTest.java26
6 files changed, 178 insertions, 5 deletions
diff --git a/src/com/android/loganalysis/item/BugreportItem.java b/src/com/android/loganalysis/item/BugreportItem.java
index 1df7d30..4b35816 100644
--- a/src/com/android/loganalysis/item/BugreportItem.java
+++ b/src/com/android/loganalysis/item/BugreportItem.java
@@ -28,6 +28,8 @@ public class BugreportItem extends GenericItem {
/** Constant for JSON output */
public static final String TIME = "TIME";
/** Constant for JSON output */
+ public static final String COMMAND_LINE = "COMMAND_LINE";
+ /** Constant for JSON output */
public static final String MEM_INFO = "MEM_INFO";
/** Constant for JSON output */
public static final String PROCRANK = "PROCRANK";
@@ -45,8 +47,10 @@ public class BugreportItem extends GenericItem {
public static final String DUMPSYS = "DUMPSYS";
private static final Set<String> ATTRIBUTES = new HashSet<String>(Arrays.asList(
- TIME, MEM_INFO, PROCRANK, TOP, KERNEL_LOG, LAST_KMSG, SYSTEM_LOG, SYSTEM_PROPS,
- DUMPSYS));
+ TIME, COMMAND_LINE, MEM_INFO, PROCRANK, TOP, KERNEL_LOG, LAST_KMSG, SYSTEM_LOG,
+ SYSTEM_PROPS, DUMPSYS));
+
+ public static class CommandLineItem extends GenericMapItem<String> {}
/**
* The constructor for {@link BugreportItem}.
@@ -70,6 +74,20 @@ public class BugreportItem extends GenericItem {
}
/**
+ * Get the {@link CommandLineItem} of the bugreport.
+ */
+ public CommandLineItem getCommandLine() {
+ return (CommandLineItem) getAttribute(COMMAND_LINE);
+ }
+
+ /**
+ * Set the {@link CommandLineItem} of the bugreport.
+ */
+ public void setCommandLine(CommandLineItem commandLine) {
+ setAttribute(COMMAND_LINE, commandLine);
+ }
+
+ /**
* Get the {@link MemInfoItem} of the bugreport.
*/
public MemInfoItem getMemInfo() {
diff --git a/src/com/android/loganalysis/item/KernelLogItem.java b/src/com/android/loganalysis/item/KernelLogItem.java
index c9ebf16..60ed4de 100644
--- a/src/com/android/loganalysis/item/KernelLogItem.java
+++ b/src/com/android/loganalysis/item/KernelLogItem.java
@@ -15,6 +15,8 @@
*/
package com.android.loganalysis.item;
+import com.android.loganalysis.parser.KernelLogParser;
+
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -91,6 +93,11 @@ public class KernelLogItem extends GenericItem {
* Add an {@link MiscKernelLogItem} event to the end of the list of events.
*/
public void addEvent(MiscKernelLogItem event) {
+ // Only take the first kernel reset
+ if (KernelLogParser.KERNEL_RESET.equals(event.getCategory()) &&
+ !getMiscEvents(KernelLogParser.KERNEL_RESET).isEmpty()) {
+ return;
+ }
((ItemList) getAttribute(EVENTS)).add(event);
}
diff --git a/src/com/android/loganalysis/parser/BugreportParser.java b/src/com/android/loganalysis/parser/BugreportParser.java
index 3947a98..604ec1a 100644
--- a/src/com/android/loganalysis/parser/BugreportParser.java
+++ b/src/com/android/loganalysis/parser/BugreportParser.java
@@ -17,11 +17,13 @@ package com.android.loganalysis.parser;
import com.android.loganalysis.item.AnrItem;
import com.android.loganalysis.item.BugreportItem;
+import com.android.loganalysis.item.BugreportItem.CommandLineItem;
import com.android.loganalysis.item.DumpsysItem;
import com.android.loganalysis.item.IItem;
import com.android.loganalysis.item.KernelLogItem;
import com.android.loganalysis.item.LogcatItem;
import com.android.loganalysis.item.MemInfoItem;
+import com.android.loganalysis.item.MiscKernelLogItem;
import com.android.loganalysis.item.MiscLogcatItem;
import com.android.loganalysis.item.ProcrankItem;
import com.android.loganalysis.item.SystemPropsItem;
@@ -55,12 +57,20 @@ public class BugreportParser extends AbstractSectionParser {
private static final String DUMPSYS_SECTION_REGEX = "------ DUMPSYS .*";
private static final String NOOP_SECTION_REGEX = "------ .*";
+ private static final String BOOTREASON = "androidboot.bootreason";
+
/**
* Matches: == dumpstate: 2012-04-26 12:13:14
*/
private static final Pattern DATE = Pattern.compile(
"^== dumpstate: (\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2})$");
+ /**
+ * Matches: Command line: key=value key=value
+ */
+ private static final Pattern COMMAND_LINE = Pattern.compile(
+ "Command line:((\\s+[^\\s=]+=[^\\s]*)*)\\s*");
+
private IParser mBugreportParser = new IParser() {
@Override
public BugreportItem parse(List<String> lines) {
@@ -73,6 +83,18 @@ public class BugreportParser extends AbstractSectionParser {
if (m.matches()) {
bugreport.setTime(parseTime(m.group(1)));
}
+ m = COMMAND_LINE.matcher(line);
+ if (m.matches()) {
+ String argString = m.group(1).trim();
+ if (!argString.isEmpty()) {
+ String[] pairs = argString.split("\\s+");
+ for (String pair : pairs) {
+ System.out.println(pair);
+ String[] keyValue = pair.split("=", 2);
+ mCommandLine.put(keyValue[0], keyValue[1]);
+ }
+ }
+ }
}
return bugreport;
}
@@ -88,6 +110,7 @@ public class BugreportParser extends AbstractSectionParser {
private DumpsysParser mDumpsysParser = new DumpsysParser();
private BugreportItem mBugreport = null;
+ private CommandLineItem mCommandLine = new CommandLineItem();
private boolean mParsedInput = false;
@@ -164,6 +187,7 @@ public class BugreportParser extends AbstractSectionParser {
}
if (mBugreport != null) {
+ mBugreport.setCommandLine(mCommandLine);
mBugreport.setMemInfo((MemInfoItem) getSection(mMemInfoParser));
mBugreport.setProcrank((ProcrankItem) getSection(mProcrankParser));
mBugreport.setTop((TopItem) getSection(mTopParser));
@@ -189,7 +213,20 @@ public class BugreportParser extends AbstractSectionParser {
mBugreport.getSystemLog() != null) {
addAnrTrace(mBugreport.getSystemLog().getAnrs(), traces.getApp(),
traces.getStack());
+ }
+ if (mCommandLine.containsKey(BOOTREASON)) {
+ String bootreason = mCommandLine.get(BOOTREASON);
+ Matcher m = KernelLogParser.BAD_BOOTREASONS.matcher(bootreason);
+ if (m.matches()) {
+ if (mBugreport.getLastKmsg() == null) {
+ mBugreport.setLastKmsg(new KernelLogItem());
+ }
+ MiscKernelLogItem item = new MiscKernelLogItem();
+ item.setStack("Last boot reason: " + bootreason.trim());
+ item.setCategory(KernelLogParser.KERNEL_RESET);
+ mBugreport.getLastKmsg().addEvent(item);
+ }
}
}
}
diff --git a/src/com/android/loganalysis/parser/KernelLogParser.java b/src/com/android/loganalysis/parser/KernelLogParser.java
index e240432..741c261 100644
--- a/src/com/android/loganalysis/parser/KernelLogParser.java
+++ b/src/com/android/loganalysis/parser/KernelLogParser.java
@@ -44,6 +44,13 @@ public class KernelLogParser implements IParser {
private static final Pattern SELINUX_DENIAL_PATTERN = Pattern.compile(
".*avc:\\s.*scontext=\\w*:\\w*:([\\w\\s]*):\\w*\\s.*");
+ /**
+ * Regular expression representing all known bootreasons which are bad.
+ */
+ public static final Pattern BAD_BOOTREASONS = Pattern.compile(
+ "(?:kernel_panic|rpm_err|hw_reset(?:$|\\n)|wdog_.*|tz_err|adsp_err|modem_err|mba_err|"
+ + "watchdogr?|Watchdog|Panic|srto:.*)");
+
private KernelLogItem mKernelLog = null;
private Double mStartTime = null;
private Double mStopTime = null;
@@ -161,16 +168,17 @@ public class KernelLogParser implements IParser {
"smem: DIAG.*",
"smsm: AMSS FATAL ERROR.*",
"kernel BUG at .*",
+ "BUG: failure at .*",
"PVR_K:\\(Fatal\\): Debug assertion failed! \\[.*\\]",
"Kernel panic.*",
+ "Unable to handle kernel paging request.*",
"BP panicked",
"WROTE DSP RAMDUMP",
"tegra_wdt: last reset due to watchdog timeout.*",
"tegra_wdt tegra_wdt.0: last reset is due to watchdog timeout.*",
"Last reset was MPU Watchdog Timer reset.*",
"\\[MODEM_IF\\].*CRASH.*",
- "Last boot reason: (?:kernel_panic|rpm_err|hw_reset(?:$|\n)|wdog_.*|" +
- "tz_err|adsp_err|modem_err|mba_err|watchdogr?|Watchdog|Panic)",
+ "Last boot reason: " + BAD_BOOTREASONS,
"Last reset was system watchdog timer reset.*",
};
for (String pattern : kernelResets) {
diff --git a/tests/src/com/android/loganalysis/parser/BugreportParserTest.java b/tests/src/com/android/loganalysis/parser/BugreportParserTest.java
index b080e0d..1eedf46 100644
--- a/tests/src/com/android/loganalysis/parser/BugreportParserTest.java
+++ b/tests/src/com/android/loganalysis/parser/BugreportParserTest.java
@@ -92,7 +92,7 @@ public class BugreportParserTest extends TestCase {
"",
"------ LAST KMSG (/proc/last_kmsg) ------",
"[ 0.000000] Initializing cgroup subsys cpu",
- "[ 16.203491] benight message",
+ "[ 16.203491] benign message",
"",
"------ SECTION ------",
"",
@@ -183,6 +183,83 @@ public class BugreportParserTest extends TestCase {
}
/**
+ * Test that the command line is parsed
+ */
+ public void testParse_command_line() {
+ List<String> lines = Arrays.asList("Command line:");
+ BugreportItem bugreport = new BugreportParser().parse(lines);
+ assertTrue(bugreport.getCommandLine().isEmpty());
+
+ lines = Arrays.asList("Command line: key=value");
+ bugreport = new BugreportParser().parse(lines);
+ assertEquals(1, bugreport.getCommandLine().size());
+ assertEquals("value", bugreport.getCommandLine().get("key"));
+
+ lines = Arrays.asList("Command line: key1=value1 key2=value2");
+ bugreport = new BugreportParser().parse(lines);
+ assertEquals(2, bugreport.getCommandLine().size());
+ assertEquals("value1", bugreport.getCommandLine().get("key1"));
+ assertEquals("value2", bugreport.getCommandLine().get("key2"));
+
+ // Test a bad strings
+ lines = Arrays.asList("Command line: key1=value=withequals key2= ");
+ bugreport = new BugreportParser().parse(lines);
+ assertEquals(2, bugreport.getCommandLine().size());
+ assertEquals("value=withequals", bugreport.getCommandLine().get("key1"));
+ assertEquals("", bugreport.getCommandLine().get("key2"));
+
+ lines = Arrays.asList("Command line: key1=value=withequals key2= key3");
+ bugreport = new BugreportParser().parse(lines);
+ assertTrue(bugreport.getCommandLine().isEmpty());
+ }
+
+ /**
+ * Test
+ */
+ public void testParse_bootreason_good() {
+ List<String> lines = Arrays.asList(
+ "========================================================",
+ "== dumpstate: 1999-01-01 02:03:04",
+ "========================================================",
+ "Command line: androidboot.bootreason=reboot",
+ "");
+ BugreportItem bugreport = new BugreportParser().parse(lines);
+ assertNull(bugreport.getLastKmsg());
+ }
+
+ public void testParse_bootreason_bad() {
+ List<String> lines = Arrays.asList(
+ "========================================================",
+ "== dumpstate: 1999-01-01 02:03:04",
+ "========================================================",
+ "Command line: androidboot.bootreason=hw_reset",
+ "");
+ BugreportItem bugreport = new BugreportParser().parse(lines);
+ assertNotNull(bugreport.getLastKmsg());
+ assertEquals(1, bugreport.getLastKmsg().getEvents().size());
+ assertEquals("Last boot reason: hw_reset",
+ bugreport.getLastKmsg().getEvents().get(0).getStack());
+ assertEquals("KERNEL_RESET", bugreport.getLastKmsg().getEvents().get(0).getCategory());
+ }
+
+ public void testParse_bootreason_duplicate() {
+ List<String> lines = Arrays.asList(
+ "========================================================",
+ "== dumpstate: 1999-01-01 02:03:04",
+ "========================================================",
+ "Command line: androidboot.bootreason=hw_reset",
+ "------ LAST KMSG (/proc/last_kmsg) ------",
+ "[ 0.000000] Initializing cgroup subsys cpu",
+ "[ 16.203491] Kernel panic",
+ "");
+ BugreportItem bugreport = new BugreportParser().parse(lines);
+ assertNotNull(bugreport.getLastKmsg());
+ assertEquals(1, bugreport.getLastKmsg().getEvents().size());
+ assertEquals("Kernel panic", bugreport.getLastKmsg().getEvents().get(0).getStack());
+ assertEquals("KERNEL_RESET", bugreport.getLastKmsg().getEvents().get(0).getCategory());
+ }
+
+ /**
* Test that the trace is set correctly if there is only one ANR.
*/
public void testSetAnrTrace_single() {
diff --git a/tests/src/com/android/loganalysis/parser/KernelLogParserTest.java b/tests/src/com/android/loganalysis/parser/KernelLogParserTest.java
index 118f3ff..890a196 100644
--- a/tests/src/com/android/loganalysis/parser/KernelLogParserTest.java
+++ b/tests/src/com/android/loganalysis/parser/KernelLogParserTest.java
@@ -212,4 +212,30 @@ public class KernelLogParserTest extends TestCase {
assertEquals(1, kernelLog.getEvents().size());
assertEquals(1, kernelLog.getMiscEvents(KernelLogParser.KERNEL_RESET).size());
}
+
+ /**
+ * Test that only the first kernel reset is taken but other signatures can have multiple
+ */
+ public void testMultipleKernelResets() {
+ final String SELINUX_DENIAL_STACK = "type=1400 audit(1384544483.730:10): avc: denied " +
+ "{ getattr } for pid=797 comm=\"Binder_5\" path=\"/dev/pts/1\" + " +
+ "dev=devpts ino=4 scontext=u:r:system_server:s0 " +
+ "tcontext=u:object_r:devpts:s0 tclass=chr_file";
+ final List<String> lines = Arrays.asList(
+ "[ 0.000000] Kernel panic",
+ "[ 0.000000] Internal error:",
+ "[ 0.000000] " + SELINUX_DENIAL_STACK,
+ "[ 1.000000] Kernel panic",
+ "[ 1.000000] Internal error:",
+ "[ 1.000000] " + SELINUX_DENIAL_STACK,
+ "[ 2.000000] Kernel panic",
+ "[ 2.000000] Internal error:",
+ "[ 2.000000] " + SELINUX_DENIAL_STACK);
+
+ KernelLogItem kernelLog = new KernelLogParser().parse(lines);
+ assertEquals(7, kernelLog.getEvents().size());
+ assertEquals(1, kernelLog.getMiscEvents(KernelLogParser.KERNEL_RESET).size());
+ assertEquals(0.0,
+ kernelLog.getMiscEvents(KernelLogParser.KERNEL_RESET).get(0).getEventTime());
+ }
}