diff --git a/src/client/linux/microdump_writer/microdump_writer.cc b/src/client/linux/microdump_writer/microdump_writer.cc index 247387e2..d54d4909 100644 --- a/src/client/linux/microdump_writer/microdump_writer.cc +++ b/src/client/linux/microdump_writer/microdump_writer.cc @@ -166,8 +166,9 @@ class MicrodumpWriter { const char kOSId[] = "L"; #endif -// We cannot depend on uts.machine. On multiarch devices it always returns the -// primary arch, not the one that match the executable being run. +// Dump the runtime architecture. On multiarch devices it might not match the +// hw architecture (the one returned by uname()), for instance in the case of +// a 32-bit app running on a aarch64 device. #if defined(__aarch64__) const char kArch[] = "arm64"; #elif defined(__ARMEL__) @@ -189,21 +190,24 @@ class MicrodumpWriter { LogAppend(" "); LogAppend(n_cpus); LogAppend(" "); + + // Dump the HW architecture (e.g., armv7l, aarch64). + struct utsname uts; + const bool has_uts_info = (uname(&uts) == 0); + const char* hwArch = has_uts_info ? uts.machine : "unknown_hw_arch"; + LogAppend(hwArch); + LogAppend(" "); + // If the client has attached a build fingerprint to the MinidumpDescriptor // use that one. Otherwise try to get some basic info from uname(). if (build_fingerprint_) { LogAppend(build_fingerprint_); + } else if (has_uts_info) { + LogAppend(uts.release); + LogAppend(" "); + LogAppend(uts.version); } else { - struct utsname uts; - if (uname(&uts) == 0) { - LogAppend(uts.machine); - LogAppend(" "); - LogAppend(uts.release); - LogAppend(" "); - LogAppend(uts.version); - } else { - LogAppend("no build fingerprint available"); - } + LogAppend("no build fingerprint available"); } LogCommitLine(); } diff --git a/src/client/linux/microdump_writer/microdump_writer_unittest.cc b/src/client/linux/microdump_writer/microdump_writer_unittest.cc index 1fa6f1ff..035e73c1 100644 --- a/src/client/linux/microdump_writer/microdump_writer_unittest.cc +++ b/src/client/linux/microdump_writer/microdump_writer_unittest.cc @@ -27,10 +27,12 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include #include #include #include +#include #include #include "breakpad_googletest_includes.h" @@ -103,7 +105,40 @@ void CrashAndGetMicrodump( buf->get(), "-----BEGIN BREAKPAD MICRODUMP-----")); ASSERT_NE(static_cast(0), strstr( buf->get(), "-----END BREAKPAD MICRODUMP-----")); +} +void CheckMicrodumpContents(const string µdum_content, + const string &expected_fingerprint, + const string &expected_product_info) { + std::istringstream iss(microdum_content); + bool did_find_os_info = false; + bool did_find_product_info = false; + for (string line; std::getline(iss, line);) { + if (line.find("O ") == 0) { + std::istringstream os_info_tokens(line); + string token; + os_info_tokens.ignore(2); // Ignore the "O " preamble. + // Check the OS descriptor char (L=Linux, A=Android). + os_info_tokens >> token; + ASSERT_TRUE(token == "L" || token == "A"); + + os_info_tokens >> token; // HW architecture. + os_info_tokens >> token; // Number of cpus. + for (size_t i = 0; i < token.size(); ++i) + ASSERT_TRUE(isxdigit(token[i])); + os_info_tokens >> token; // SW architecture. + + // Check that the build fingerprint is in the right place. + os_info_tokens >> token; + ASSERT_EQ(expected_fingerprint, token); + did_find_os_info = true; + } else if (line.find("V ") == 0) { + ASSERT_EQ("V " + expected_product_info, line); + did_find_product_info = true; + } + } + ASSERT_TRUE(did_find_os_info); + ASSERT_TRUE(did_find_product_info); } TEST(MicrodumpWriterTest, BasicWithMappings) { @@ -156,9 +191,15 @@ TEST(MicrodumpWriterTest, BuildFingerprintAndProductInfo) { MappingList no_mappings; CrashAndGetMicrodump(no_mappings, kBuildFingerprint, kProductInfo, &buf); - - ASSERT_NE(static_cast(0), strstr(buf.get(), kBuildFingerprint)); - ASSERT_NE(static_cast(0), strstr(buf.get(), kProductInfo)); + CheckMicrodumpContents(string(buf.get()), kBuildFingerprint, kProductInfo); } +TEST(MicrodumpWriterTest, NoProductInfo) { + const char kBuildFingerprint[] = "foobar"; + scoped_array buf; + MappingList no_mappings; + + CrashAndGetMicrodump(no_mappings, kBuildFingerprint, NULL, &buf); + CheckMicrodumpContents(string(buf.get()), kBuildFingerprint, "UNKNOWN:0.0.0.0"); +} } // namespace