diff --git a/Makefile.am b/Makefile.am index aba3598f..ebeda7a0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in -# Copyright (c) 2006, Google Inc. +# Copyright (c) 2010, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -135,7 +135,9 @@ check_PROGRAMS = \ src/processor/minidump_unittest \ src/processor/pathname_stripper_unittest \ src/processor/postfix_evaluator_unittest \ - src/processor/range_map_unittest + src/processor/range_map_unittest \ + src/processor/synth_minidump_unittest \ + src/processor/test_assembler_unittest if SELFTEST check_PROGRAMS += \ @@ -230,7 +232,10 @@ src_processor_minidump_processor_unittest_LDADD = \ src_processor_minidump_unittest_SOURCES = \ src/processor/minidump_unittest.cc \ + src/processor/synth_minidump.cc \ + src/processor/test_assembler.cc \ src/testing/gtest/src/gtest-all.cc \ + src/testing/gtest/src/gtest_main.cc \ src/testing/src/gmock-all.cc src_processor_minidump_unittest_CPPFLAGS = \ -I$(top_srcdir)/src/testing/include \ @@ -276,6 +281,34 @@ src_processor_stackwalker_selftest_LDADD = \ src/processor/stackwalker_sparc.lo \ src/processor/stackwalker_x86.lo +src_processor_synth_minidump_unittest_SOURCES = \ + src/processor/synth_minidump_unittest.cc \ + src/testing/gtest/src/gtest-all.cc \ + src/testing/gtest/src/gtest_main.cc \ + src/testing/src/gmock-all.cc \ + src/processor/synth_minidump.cc \ + src/processor/synth_minidump.h \ + src/processor/test_assembler.cc \ + src/processor/test_assembler.h +src_processor_synth_minidump_unittest_CPPFLAGS = \ + -I$(top_srcdir)/src/testing/include \ + -I$(top_srcdir)/src/testing/gtest/include \ + -I$(top_srcdir)/src/testing/gtest \ + -I$(top_srcdir)/src/testing + +src_processor_test_assembler_unittest_SOURCES = \ + src/processor/test_assembler_unittest.cc \ + src/testing/gtest/src/gtest-all.cc \ + src/testing/gtest/src/gtest_main.cc \ + src/testing/src/gmock-all.cc \ + src/processor/test_assembler.cc \ + src/processor/test_assembler.h +src_processor_test_assembler_unittest_CPPFLAGS = \ + -I$(top_srcdir)/src/testing/include \ + -I$(top_srcdir)/src/testing/gtest/include \ + -I$(top_srcdir)/src/testing/gtest \ + -I$(top_srcdir)/src/testing + ## Non-installables noinst_PROGRAMS = noinst_SCRIPTS = $(check_SCRIPTS) diff --git a/Makefile.in b/Makefile.in index dff449db..d4d4ecc7 100644 --- a/Makefile.in +++ b/Makefile.in @@ -15,7 +15,7 @@ @SET_MAKE@ -# Copyright (c) 2006, Google Inc. +# Copyright (c) 2010, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -77,7 +77,9 @@ check_PROGRAMS = src/client/linux/linux_client_unittest$(EXEEXT) \ src/processor/minidump_unittest$(EXEEXT) \ src/processor/pathname_stripper_unittest$(EXEEXT) \ src/processor/postfix_evaluator_unittest$(EXEEXT) \ - src/processor/range_map_unittest$(EXEEXT) $(am__EXEEXT_1) + src/processor/range_map_unittest$(EXEEXT) \ + src/processor/synth_minidump_unittest$(EXEEXT) \ + src/processor/test_assembler_unittest$(EXEEXT) $(am__EXEEXT_1) @SELFTEST_TRUE@am__append_1 = \ @SELFTEST_TRUE@ src/processor/stackwalker_selftest @@ -236,7 +238,10 @@ src_processor_minidump_stackwalk_DEPENDENCIES = \ src/processor/stackwalker_sparc.lo \ src/processor/stackwalker_x86.lo am_src_processor_minidump_unittest_OBJECTS = src/processor/src_processor_minidump_unittest-minidump_unittest.$(OBJEXT) \ + src/processor/src_processor_minidump_unittest-synth_minidump.$(OBJEXT) \ + src/processor/src_processor_minidump_unittest-test_assembler.$(OBJEXT) \ src/testing/gtest/src/src_processor_minidump_unittest-gtest-all.$(OBJEXT) \ + src/testing/gtest/src/src_processor_minidump_unittest-gtest_main.$(OBJEXT) \ src/testing/src/src_processor_minidump_unittest-gmock-all.$(OBJEXT) src_processor_minidump_unittest_OBJECTS = \ $(am_src_processor_minidump_unittest_OBJECTS) @@ -276,6 +281,23 @@ src_processor_stackwalker_selftest_DEPENDENCIES = \ src/processor/stackwalker_ppc.lo \ src/processor/stackwalker_sparc.lo \ src/processor/stackwalker_x86.lo +am_src_processor_synth_minidump_unittest_OBJECTS = src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.$(OBJEXT) \ + src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest-all.$(OBJEXT) \ + src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest_main.$(OBJEXT) \ + src/testing/src/src_processor_synth_minidump_unittest-gmock-all.$(OBJEXT) \ + src/processor/src_processor_synth_minidump_unittest-synth_minidump.$(OBJEXT) \ + src/processor/src_processor_synth_minidump_unittest-test_assembler.$(OBJEXT) +src_processor_synth_minidump_unittest_OBJECTS = \ + $(am_src_processor_synth_minidump_unittest_OBJECTS) +src_processor_synth_minidump_unittest_LDADD = $(LDADD) +am_src_processor_test_assembler_unittest_OBJECTS = src/processor/src_processor_test_assembler_unittest-test_assembler_unittest.$(OBJEXT) \ + src/testing/gtest/src/src_processor_test_assembler_unittest-gtest-all.$(OBJEXT) \ + src/testing/gtest/src/src_processor_test_assembler_unittest-gtest_main.$(OBJEXT) \ + src/testing/src/src_processor_test_assembler_unittest-gmock-all.$(OBJEXT) \ + src/processor/src_processor_test_assembler_unittest-test_assembler.$(OBJEXT) +src_processor_test_assembler_unittest_OBJECTS = \ + $(am_src_processor_test_assembler_unittest_OBJECTS) +src_processor_test_assembler_unittest_LDADD = $(LDADD) SCRIPTS = $(noinst_SCRIPTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src depcomp = $(SHELL) $(top_srcdir)/autotools/depcomp @@ -313,7 +335,9 @@ SOURCES = $(src_client_linux_libbreakpad_client_la_SOURCES) \ $(src_processor_pathname_stripper_unittest_SOURCES) \ $(src_processor_postfix_evaluator_unittest_SOURCES) \ $(src_processor_range_map_unittest_SOURCES) \ - $(src_processor_stackwalker_selftest_SOURCES) + $(src_processor_stackwalker_selftest_SOURCES) \ + $(src_processor_synth_minidump_unittest_SOURCES) \ + $(src_processor_test_assembler_unittest_SOURCES) DIST_SOURCES = $(src_client_linux_libbreakpad_client_la_SOURCES) \ $(src_libbreakpad_la_SOURCES) \ $(src_client_linux_linux_client_unittest_SOURCES) \ @@ -328,7 +352,9 @@ DIST_SOURCES = $(src_client_linux_libbreakpad_client_la_SOURCES) \ $(src_processor_pathname_stripper_unittest_SOURCES) \ $(src_processor_postfix_evaluator_unittest_SOURCES) \ $(src_processor_range_map_unittest_SOURCES) \ - $(src_processor_stackwalker_selftest_SOURCES) + $(src_processor_stackwalker_selftest_SOURCES) \ + $(src_processor_synth_minidump_unittest_SOURCES) \ + $(src_processor_test_assembler_unittest_SOURCES) DATA = $(dist_doc_DATA) ETAGS = etags CTAGS = ctags @@ -641,7 +667,10 @@ src_processor_minidump_processor_unittest_LDADD = \ src_processor_minidump_unittest_SOURCES = \ src/processor/minidump_unittest.cc \ + src/processor/synth_minidump.cc \ + src/processor/test_assembler.cc \ src/testing/gtest/src/gtest-all.cc \ + src/testing/gtest/src/gtest_main.cc \ src/testing/src/gmock-all.cc src_processor_minidump_unittest_CPPFLAGS = \ @@ -693,6 +722,36 @@ src_processor_stackwalker_selftest_LDADD = \ src/processor/stackwalker_sparc.lo \ src/processor/stackwalker_x86.lo +src_processor_synth_minidump_unittest_SOURCES = \ + src/processor/synth_minidump_unittest.cc \ + src/testing/gtest/src/gtest-all.cc \ + src/testing/gtest/src/gtest_main.cc \ + src/testing/src/gmock-all.cc \ + src/processor/synth_minidump.cc \ + src/processor/synth_minidump.h \ + src/processor/test_assembler.cc \ + src/processor/test_assembler.h + +src_processor_synth_minidump_unittest_CPPFLAGS = \ + -I$(top_srcdir)/src/testing/include \ + -I$(top_srcdir)/src/testing/gtest/include \ + -I$(top_srcdir)/src/testing/gtest \ + -I$(top_srcdir)/src/testing + +src_processor_test_assembler_unittest_SOURCES = \ + src/processor/test_assembler_unittest.cc \ + src/testing/gtest/src/gtest-all.cc \ + src/testing/gtest/src/gtest_main.cc \ + src/testing/src/gmock-all.cc \ + src/processor/test_assembler.cc \ + src/processor/test_assembler.h + +src_processor_test_assembler_unittest_CPPFLAGS = \ + -I$(top_srcdir)/src/testing/include \ + -I$(top_srcdir)/src/testing/gtest/include \ + -I$(top_srcdir)/src/testing/gtest \ + -I$(top_srcdir)/src/testing + noinst_SCRIPTS = $(check_SCRIPTS) src_processor_minidump_dump_SOURCES = \ src/processor/minidump_dump.cc @@ -1198,9 +1257,18 @@ src/processor/minidump_stackwalk$(EXEEXT): $(src_processor_minidump_stackwalk_OB src/processor/src_processor_minidump_unittest-minidump_unittest.$(OBJEXT): \ src/processor/$(am__dirstamp) \ src/processor/$(DEPDIR)/$(am__dirstamp) +src/processor/src_processor_minidump_unittest-synth_minidump.$(OBJEXT): \ + src/processor/$(am__dirstamp) \ + src/processor/$(DEPDIR)/$(am__dirstamp) +src/processor/src_processor_minidump_unittest-test_assembler.$(OBJEXT): \ + src/processor/$(am__dirstamp) \ + src/processor/$(DEPDIR)/$(am__dirstamp) src/testing/gtest/src/src_processor_minidump_unittest-gtest-all.$(OBJEXT): \ src/testing/gtest/src/$(am__dirstamp) \ src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp) +src/testing/gtest/src/src_processor_minidump_unittest-gtest_main.$(OBJEXT): \ + src/testing/gtest/src/$(am__dirstamp) \ + src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp) src/testing/src/src_processor_minidump_unittest-gmock-all.$(OBJEXT): \ src/testing/src/$(am__dirstamp) \ src/testing/src/$(DEPDIR)/$(am__dirstamp) @@ -1231,6 +1299,45 @@ src/processor/stackwalker_selftest.$(OBJEXT): \ src/processor/stackwalker_selftest$(EXEEXT): $(src_processor_stackwalker_selftest_OBJECTS) $(src_processor_stackwalker_selftest_DEPENDENCIES) src/processor/$(am__dirstamp) @rm -f src/processor/stackwalker_selftest$(EXEEXT) $(CXXLINK) $(src_processor_stackwalker_selftest_OBJECTS) $(src_processor_stackwalker_selftest_LDADD) $(LIBS) +src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.$(OBJEXT): \ + src/processor/$(am__dirstamp) \ + src/processor/$(DEPDIR)/$(am__dirstamp) +src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest-all.$(OBJEXT): \ + src/testing/gtest/src/$(am__dirstamp) \ + src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp) +src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest_main.$(OBJEXT): \ + src/testing/gtest/src/$(am__dirstamp) \ + src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp) +src/testing/src/src_processor_synth_minidump_unittest-gmock-all.$(OBJEXT): \ + src/testing/src/$(am__dirstamp) \ + src/testing/src/$(DEPDIR)/$(am__dirstamp) +src/processor/src_processor_synth_minidump_unittest-synth_minidump.$(OBJEXT): \ + src/processor/$(am__dirstamp) \ + src/processor/$(DEPDIR)/$(am__dirstamp) +src/processor/src_processor_synth_minidump_unittest-test_assembler.$(OBJEXT): \ + src/processor/$(am__dirstamp) \ + src/processor/$(DEPDIR)/$(am__dirstamp) +src/processor/synth_minidump_unittest$(EXEEXT): $(src_processor_synth_minidump_unittest_OBJECTS) $(src_processor_synth_minidump_unittest_DEPENDENCIES) src/processor/$(am__dirstamp) + @rm -f src/processor/synth_minidump_unittest$(EXEEXT) + $(CXXLINK) $(src_processor_synth_minidump_unittest_OBJECTS) $(src_processor_synth_minidump_unittest_LDADD) $(LIBS) +src/processor/src_processor_test_assembler_unittest-test_assembler_unittest.$(OBJEXT): \ + src/processor/$(am__dirstamp) \ + src/processor/$(DEPDIR)/$(am__dirstamp) +src/testing/gtest/src/src_processor_test_assembler_unittest-gtest-all.$(OBJEXT): \ + src/testing/gtest/src/$(am__dirstamp) \ + src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp) +src/testing/gtest/src/src_processor_test_assembler_unittest-gtest_main.$(OBJEXT): \ + src/testing/gtest/src/$(am__dirstamp) \ + src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp) +src/testing/src/src_processor_test_assembler_unittest-gmock-all.$(OBJEXT): \ + src/testing/src/$(am__dirstamp) \ + src/testing/src/$(DEPDIR)/$(am__dirstamp) +src/processor/src_processor_test_assembler_unittest-test_assembler.$(OBJEXT): \ + src/processor/$(am__dirstamp) \ + src/processor/$(DEPDIR)/$(am__dirstamp) +src/processor/test_assembler_unittest$(EXEEXT): $(src_processor_test_assembler_unittest_OBJECTS) $(src_processor_test_assembler_unittest_DEPENDENCIES) src/processor/$(am__dirstamp) + @rm -f src/processor/test_assembler_unittest$(EXEEXT) + $(CXXLINK) $(src_processor_test_assembler_unittest_OBJECTS) $(src_processor_test_assembler_unittest_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -1288,6 +1395,13 @@ mostlyclean-compile: -rm -f src/processor/simple_symbol_supplier.lo -rm -f src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.$(OBJEXT) -rm -f src/processor/src_processor_minidump_unittest-minidump_unittest.$(OBJEXT) + -rm -f src/processor/src_processor_minidump_unittest-synth_minidump.$(OBJEXT) + -rm -f src/processor/src_processor_minidump_unittest-test_assembler.$(OBJEXT) + -rm -f src/processor/src_processor_synth_minidump_unittest-synth_minidump.$(OBJEXT) + -rm -f src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.$(OBJEXT) + -rm -f src/processor/src_processor_synth_minidump_unittest-test_assembler.$(OBJEXT) + -rm -f src/processor/src_processor_test_assembler_unittest-test_assembler.$(OBJEXT) + -rm -f src/processor/src_processor_test_assembler_unittest-test_assembler_unittest.$(OBJEXT) -rm -f src/processor/stackwalker.$(OBJEXT) -rm -f src/processor/stackwalker.lo -rm -f src/processor/stackwalker_amd64.$(OBJEXT) @@ -1305,9 +1419,16 @@ mostlyclean-compile: -rm -f src/testing/gtest/src/src_client_linux_linux_client_unittest-gtest_main.$(OBJEXT) -rm -f src/testing/gtest/src/src_processor_minidump_processor_unittest-gtest-all.$(OBJEXT) -rm -f src/testing/gtest/src/src_processor_minidump_unittest-gtest-all.$(OBJEXT) + -rm -f src/testing/gtest/src/src_processor_minidump_unittest-gtest_main.$(OBJEXT) + -rm -f src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest-all.$(OBJEXT) + -rm -f src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest_main.$(OBJEXT) + -rm -f src/testing/gtest/src/src_processor_test_assembler_unittest-gtest-all.$(OBJEXT) + -rm -f src/testing/gtest/src/src_processor_test_assembler_unittest-gtest_main.$(OBJEXT) -rm -f src/testing/src/src_client_linux_linux_client_unittest-gmock-all.$(OBJEXT) -rm -f src/testing/src/src_processor_minidump_processor_unittest-gmock-all.$(OBJEXT) -rm -f src/testing/src/src_processor_minidump_unittest-gmock-all.$(OBJEXT) + -rm -f src/testing/src/src_processor_synth_minidump_unittest-gmock-all.$(OBJEXT) + -rm -f src/testing/src/src_processor_test_assembler_unittest-gmock-all.$(OBJEXT) distclean-compile: -rm -f *.tab.c @@ -1347,6 +1468,13 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/simple_symbol_supplier.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_minidump_processor_unittest-minidump_processor_unittest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_minidump_unittest-minidump_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_minidump_unittest-synth_minidump.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_minidump_unittest-test_assembler.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-test_assembler.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_test_assembler_unittest-test_assembler.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_test_assembler_unittest-test_assembler_unittest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker_amd64.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker_arm.Plo@am__quote@ @@ -1358,9 +1486,16 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_client_linux_linux_client_unittest-gtest_main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_processor_minidump_processor_unittest-gtest-all.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_processor_minidump_unittest-gtest-all.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_processor_minidump_unittest-gtest_main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gtest-all.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gtest_main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_processor_test_assembler_unittest-gtest-all.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_processor_test_assembler_unittest-gtest_main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_client_linux_linux_client_unittest-gmock-all.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_processor_minidump_processor_unittest-gmock-all.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_processor_minidump_unittest-gmock-all.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gmock-all.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_processor_test_assembler_unittest-gmock-all.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @@ -1592,6 +1727,34 @@ src/processor/src_processor_minidump_unittest-minidump_unittest.obj: src/process @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_minidump_unittest-minidump_unittest.obj `if test -f 'src/processor/minidump_unittest.cc'; then $(CYGPATH_W) 'src/processor/minidump_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/minidump_unittest.cc'; fi` +src/processor/src_processor_minidump_unittest-synth_minidump.o: src/processor/synth_minidump.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_minidump_unittest-synth_minidump.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_minidump_unittest-synth_minidump.Tpo -c -o src/processor/src_processor_minidump_unittest-synth_minidump.o `test -f 'src/processor/synth_minidump.cc' || echo '$(srcdir)/'`src/processor/synth_minidump.cc +@am__fastdepCXX_TRUE@ $(am__mv) src/processor/$(DEPDIR)/src_processor_minidump_unittest-synth_minidump.Tpo src/processor/$(DEPDIR)/src_processor_minidump_unittest-synth_minidump.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/processor/synth_minidump.cc' object='src/processor/src_processor_minidump_unittest-synth_minidump.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_minidump_unittest-synth_minidump.o `test -f 'src/processor/synth_minidump.cc' || echo '$(srcdir)/'`src/processor/synth_minidump.cc + +src/processor/src_processor_minidump_unittest-synth_minidump.obj: src/processor/synth_minidump.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_minidump_unittest-synth_minidump.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_minidump_unittest-synth_minidump.Tpo -c -o src/processor/src_processor_minidump_unittest-synth_minidump.obj `if test -f 'src/processor/synth_minidump.cc'; then $(CYGPATH_W) 'src/processor/synth_minidump.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/synth_minidump.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) src/processor/$(DEPDIR)/src_processor_minidump_unittest-synth_minidump.Tpo src/processor/$(DEPDIR)/src_processor_minidump_unittest-synth_minidump.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/processor/synth_minidump.cc' object='src/processor/src_processor_minidump_unittest-synth_minidump.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_minidump_unittest-synth_minidump.obj `if test -f 'src/processor/synth_minidump.cc'; then $(CYGPATH_W) 'src/processor/synth_minidump.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/synth_minidump.cc'; fi` + +src/processor/src_processor_minidump_unittest-test_assembler.o: src/processor/test_assembler.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_minidump_unittest-test_assembler.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_minidump_unittest-test_assembler.Tpo -c -o src/processor/src_processor_minidump_unittest-test_assembler.o `test -f 'src/processor/test_assembler.cc' || echo '$(srcdir)/'`src/processor/test_assembler.cc +@am__fastdepCXX_TRUE@ $(am__mv) src/processor/$(DEPDIR)/src_processor_minidump_unittest-test_assembler.Tpo src/processor/$(DEPDIR)/src_processor_minidump_unittest-test_assembler.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/processor/test_assembler.cc' object='src/processor/src_processor_minidump_unittest-test_assembler.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_minidump_unittest-test_assembler.o `test -f 'src/processor/test_assembler.cc' || echo '$(srcdir)/'`src/processor/test_assembler.cc + +src/processor/src_processor_minidump_unittest-test_assembler.obj: src/processor/test_assembler.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_minidump_unittest-test_assembler.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_minidump_unittest-test_assembler.Tpo -c -o src/processor/src_processor_minidump_unittest-test_assembler.obj `if test -f 'src/processor/test_assembler.cc'; then $(CYGPATH_W) 'src/processor/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/test_assembler.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) src/processor/$(DEPDIR)/src_processor_minidump_unittest-test_assembler.Tpo src/processor/$(DEPDIR)/src_processor_minidump_unittest-test_assembler.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/processor/test_assembler.cc' object='src/processor/src_processor_minidump_unittest-test_assembler.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_minidump_unittest-test_assembler.obj `if test -f 'src/processor/test_assembler.cc'; then $(CYGPATH_W) 'src/processor/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/test_assembler.cc'; fi` + src/testing/gtest/src/src_processor_minidump_unittest-gtest-all.o: src/testing/gtest/src/gtest-all.cc @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_processor_minidump_unittest-gtest-all.o -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_processor_minidump_unittest-gtest-all.Tpo -c -o src/testing/gtest/src/src_processor_minidump_unittest-gtest-all.o `test -f 'src/testing/gtest/src/gtest-all.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest-all.cc @am__fastdepCXX_TRUE@ $(am__mv) src/testing/gtest/src/$(DEPDIR)/src_processor_minidump_unittest-gtest-all.Tpo src/testing/gtest/src/$(DEPDIR)/src_processor_minidump_unittest-gtest-all.Po @@ -1606,6 +1769,20 @@ src/testing/gtest/src/src_processor_minidump_unittest-gtest-all.obj: src/testing @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_processor_minidump_unittest-gtest-all.obj `if test -f 'src/testing/gtest/src/gtest-all.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest-all.cc'; fi` +src/testing/gtest/src/src_processor_minidump_unittest-gtest_main.o: src/testing/gtest/src/gtest_main.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_processor_minidump_unittest-gtest_main.o -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_processor_minidump_unittest-gtest_main.Tpo -c -o src/testing/gtest/src/src_processor_minidump_unittest-gtest_main.o `test -f 'src/testing/gtest/src/gtest_main.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest_main.cc +@am__fastdepCXX_TRUE@ $(am__mv) src/testing/gtest/src/$(DEPDIR)/src_processor_minidump_unittest-gtest_main.Tpo src/testing/gtest/src/$(DEPDIR)/src_processor_minidump_unittest-gtest_main.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/gtest/src/gtest_main.cc' object='src/testing/gtest/src/src_processor_minidump_unittest-gtest_main.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_processor_minidump_unittest-gtest_main.o `test -f 'src/testing/gtest/src/gtest_main.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest_main.cc + +src/testing/gtest/src/src_processor_minidump_unittest-gtest_main.obj: src/testing/gtest/src/gtest_main.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_processor_minidump_unittest-gtest_main.obj -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_processor_minidump_unittest-gtest_main.Tpo -c -o src/testing/gtest/src/src_processor_minidump_unittest-gtest_main.obj `if test -f 'src/testing/gtest/src/gtest_main.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest_main.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest_main.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) src/testing/gtest/src/$(DEPDIR)/src_processor_minidump_unittest-gtest_main.Tpo src/testing/gtest/src/$(DEPDIR)/src_processor_minidump_unittest-gtest_main.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/gtest/src/gtest_main.cc' object='src/testing/gtest/src/src_processor_minidump_unittest-gtest_main.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_processor_minidump_unittest-gtest_main.obj `if test -f 'src/testing/gtest/src/gtest_main.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest_main.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest_main.cc'; fi` + src/testing/src/src_processor_minidump_unittest-gmock-all.o: src/testing/src/gmock-all.cc @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/src/src_processor_minidump_unittest-gmock-all.o -MD -MP -MF src/testing/src/$(DEPDIR)/src_processor_minidump_unittest-gmock-all.Tpo -c -o src/testing/src/src_processor_minidump_unittest-gmock-all.o `test -f 'src/testing/src/gmock-all.cc' || echo '$(srcdir)/'`src/testing/src/gmock-all.cc @am__fastdepCXX_TRUE@ $(am__mv) src/testing/src/$(DEPDIR)/src_processor_minidump_unittest-gmock-all.Tpo src/testing/src/$(DEPDIR)/src_processor_minidump_unittest-gmock-all.Po @@ -1620,6 +1797,160 @@ src/testing/src/src_processor_minidump_unittest-gmock-all.obj: src/testing/src/g @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/src/src_processor_minidump_unittest-gmock-all.obj `if test -f 'src/testing/src/gmock-all.cc'; then $(CYGPATH_W) 'src/testing/src/gmock-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/src/gmock-all.cc'; fi` +src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.o: src/processor/synth_minidump_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump_unittest.Tpo -c -o src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.o `test -f 'src/processor/synth_minidump_unittest.cc' || echo '$(srcdir)/'`src/processor/synth_minidump_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump_unittest.Tpo src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/processor/synth_minidump_unittest.cc' object='src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.o `test -f 'src/processor/synth_minidump_unittest.cc' || echo '$(srcdir)/'`src/processor/synth_minidump_unittest.cc + +src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.obj: src/processor/synth_minidump_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump_unittest.Tpo -c -o src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.obj `if test -f 'src/processor/synth_minidump_unittest.cc'; then $(CYGPATH_W) 'src/processor/synth_minidump_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/synth_minidump_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump_unittest.Tpo src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/processor/synth_minidump_unittest.cc' object='src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_synth_minidump_unittest-synth_minidump_unittest.obj `if test -f 'src/processor/synth_minidump_unittest.cc'; then $(CYGPATH_W) 'src/processor/synth_minidump_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/synth_minidump_unittest.cc'; fi` + +src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest-all.o: src/testing/gtest/src/gtest-all.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest-all.o -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gtest-all.Tpo -c -o src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest-all.o `test -f 'src/testing/gtest/src/gtest-all.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest-all.cc +@am__fastdepCXX_TRUE@ $(am__mv) src/testing/gtest/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gtest-all.Tpo src/testing/gtest/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gtest-all.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/gtest/src/gtest-all.cc' object='src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest-all.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest-all.o `test -f 'src/testing/gtest/src/gtest-all.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest-all.cc + +src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest-all.obj: src/testing/gtest/src/gtest-all.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest-all.obj -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gtest-all.Tpo -c -o src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest-all.obj `if test -f 'src/testing/gtest/src/gtest-all.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest-all.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) src/testing/gtest/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gtest-all.Tpo src/testing/gtest/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gtest-all.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/gtest/src/gtest-all.cc' object='src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest-all.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest-all.obj `if test -f 'src/testing/gtest/src/gtest-all.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest-all.cc'; fi` + +src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest_main.o: src/testing/gtest/src/gtest_main.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest_main.o -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gtest_main.Tpo -c -o src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest_main.o `test -f 'src/testing/gtest/src/gtest_main.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest_main.cc +@am__fastdepCXX_TRUE@ $(am__mv) src/testing/gtest/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gtest_main.Tpo src/testing/gtest/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gtest_main.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/gtest/src/gtest_main.cc' object='src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest_main.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest_main.o `test -f 'src/testing/gtest/src/gtest_main.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest_main.cc + +src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest_main.obj: src/testing/gtest/src/gtest_main.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest_main.obj -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gtest_main.Tpo -c -o src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest_main.obj `if test -f 'src/testing/gtest/src/gtest_main.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest_main.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest_main.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) src/testing/gtest/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gtest_main.Tpo src/testing/gtest/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gtest_main.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/gtest/src/gtest_main.cc' object='src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest_main.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest_main.obj `if test -f 'src/testing/gtest/src/gtest_main.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest_main.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest_main.cc'; fi` + +src/testing/src/src_processor_synth_minidump_unittest-gmock-all.o: src/testing/src/gmock-all.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/src/src_processor_synth_minidump_unittest-gmock-all.o -MD -MP -MF src/testing/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gmock-all.Tpo -c -o src/testing/src/src_processor_synth_minidump_unittest-gmock-all.o `test -f 'src/testing/src/gmock-all.cc' || echo '$(srcdir)/'`src/testing/src/gmock-all.cc +@am__fastdepCXX_TRUE@ $(am__mv) src/testing/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gmock-all.Tpo src/testing/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gmock-all.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/src/gmock-all.cc' object='src/testing/src/src_processor_synth_minidump_unittest-gmock-all.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/src/src_processor_synth_minidump_unittest-gmock-all.o `test -f 'src/testing/src/gmock-all.cc' || echo '$(srcdir)/'`src/testing/src/gmock-all.cc + +src/testing/src/src_processor_synth_minidump_unittest-gmock-all.obj: src/testing/src/gmock-all.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/src/src_processor_synth_minidump_unittest-gmock-all.obj -MD -MP -MF src/testing/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gmock-all.Tpo -c -o src/testing/src/src_processor_synth_minidump_unittest-gmock-all.obj `if test -f 'src/testing/src/gmock-all.cc'; then $(CYGPATH_W) 'src/testing/src/gmock-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/src/gmock-all.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) src/testing/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gmock-all.Tpo src/testing/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gmock-all.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/src/gmock-all.cc' object='src/testing/src/src_processor_synth_minidump_unittest-gmock-all.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/src/src_processor_synth_minidump_unittest-gmock-all.obj `if test -f 'src/testing/src/gmock-all.cc'; then $(CYGPATH_W) 'src/testing/src/gmock-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/src/gmock-all.cc'; fi` + +src/processor/src_processor_synth_minidump_unittest-synth_minidump.o: src/processor/synth_minidump.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_synth_minidump_unittest-synth_minidump.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump.Tpo -c -o src/processor/src_processor_synth_minidump_unittest-synth_minidump.o `test -f 'src/processor/synth_minidump.cc' || echo '$(srcdir)/'`src/processor/synth_minidump.cc +@am__fastdepCXX_TRUE@ $(am__mv) src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump.Tpo src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/processor/synth_minidump.cc' object='src/processor/src_processor_synth_minidump_unittest-synth_minidump.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_synth_minidump_unittest-synth_minidump.o `test -f 'src/processor/synth_minidump.cc' || echo '$(srcdir)/'`src/processor/synth_minidump.cc + +src/processor/src_processor_synth_minidump_unittest-synth_minidump.obj: src/processor/synth_minidump.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_synth_minidump_unittest-synth_minidump.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump.Tpo -c -o src/processor/src_processor_synth_minidump_unittest-synth_minidump.obj `if test -f 'src/processor/synth_minidump.cc'; then $(CYGPATH_W) 'src/processor/synth_minidump.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/synth_minidump.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump.Tpo src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-synth_minidump.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/processor/synth_minidump.cc' object='src/processor/src_processor_synth_minidump_unittest-synth_minidump.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_synth_minidump_unittest-synth_minidump.obj `if test -f 'src/processor/synth_minidump.cc'; then $(CYGPATH_W) 'src/processor/synth_minidump.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/synth_minidump.cc'; fi` + +src/processor/src_processor_synth_minidump_unittest-test_assembler.o: src/processor/test_assembler.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_synth_minidump_unittest-test_assembler.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-test_assembler.Tpo -c -o src/processor/src_processor_synth_minidump_unittest-test_assembler.o `test -f 'src/processor/test_assembler.cc' || echo '$(srcdir)/'`src/processor/test_assembler.cc +@am__fastdepCXX_TRUE@ $(am__mv) src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-test_assembler.Tpo src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-test_assembler.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/processor/test_assembler.cc' object='src/processor/src_processor_synth_minidump_unittest-test_assembler.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_synth_minidump_unittest-test_assembler.o `test -f 'src/processor/test_assembler.cc' || echo '$(srcdir)/'`src/processor/test_assembler.cc + +src/processor/src_processor_synth_minidump_unittest-test_assembler.obj: src/processor/test_assembler.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_synth_minidump_unittest-test_assembler.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-test_assembler.Tpo -c -o src/processor/src_processor_synth_minidump_unittest-test_assembler.obj `if test -f 'src/processor/test_assembler.cc'; then $(CYGPATH_W) 'src/processor/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/test_assembler.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-test_assembler.Tpo src/processor/$(DEPDIR)/src_processor_synth_minidump_unittest-test_assembler.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/processor/test_assembler.cc' object='src/processor/src_processor_synth_minidump_unittest-test_assembler.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_synth_minidump_unittest-test_assembler.obj `if test -f 'src/processor/test_assembler.cc'; then $(CYGPATH_W) 'src/processor/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/test_assembler.cc'; fi` + +src/processor/src_processor_test_assembler_unittest-test_assembler_unittest.o: src/processor/test_assembler_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_test_assembler_unittest-test_assembler_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_test_assembler_unittest-test_assembler_unittest.Tpo -c -o src/processor/src_processor_test_assembler_unittest-test_assembler_unittest.o `test -f 'src/processor/test_assembler_unittest.cc' || echo '$(srcdir)/'`src/processor/test_assembler_unittest.cc +@am__fastdepCXX_TRUE@ $(am__mv) src/processor/$(DEPDIR)/src_processor_test_assembler_unittest-test_assembler_unittest.Tpo src/processor/$(DEPDIR)/src_processor_test_assembler_unittest-test_assembler_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/processor/test_assembler_unittest.cc' object='src/processor/src_processor_test_assembler_unittest-test_assembler_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_test_assembler_unittest-test_assembler_unittest.o `test -f 'src/processor/test_assembler_unittest.cc' || echo '$(srcdir)/'`src/processor/test_assembler_unittest.cc + +src/processor/src_processor_test_assembler_unittest-test_assembler_unittest.obj: src/processor/test_assembler_unittest.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_test_assembler_unittest-test_assembler_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_test_assembler_unittest-test_assembler_unittest.Tpo -c -o src/processor/src_processor_test_assembler_unittest-test_assembler_unittest.obj `if test -f 'src/processor/test_assembler_unittest.cc'; then $(CYGPATH_W) 'src/processor/test_assembler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/test_assembler_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) src/processor/$(DEPDIR)/src_processor_test_assembler_unittest-test_assembler_unittest.Tpo src/processor/$(DEPDIR)/src_processor_test_assembler_unittest-test_assembler_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/processor/test_assembler_unittest.cc' object='src/processor/src_processor_test_assembler_unittest-test_assembler_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_test_assembler_unittest-test_assembler_unittest.obj `if test -f 'src/processor/test_assembler_unittest.cc'; then $(CYGPATH_W) 'src/processor/test_assembler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/test_assembler_unittest.cc'; fi` + +src/testing/gtest/src/src_processor_test_assembler_unittest-gtest-all.o: src/testing/gtest/src/gtest-all.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_processor_test_assembler_unittest-gtest-all.o -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_processor_test_assembler_unittest-gtest-all.Tpo -c -o src/testing/gtest/src/src_processor_test_assembler_unittest-gtest-all.o `test -f 'src/testing/gtest/src/gtest-all.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest-all.cc +@am__fastdepCXX_TRUE@ $(am__mv) src/testing/gtest/src/$(DEPDIR)/src_processor_test_assembler_unittest-gtest-all.Tpo src/testing/gtest/src/$(DEPDIR)/src_processor_test_assembler_unittest-gtest-all.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/gtest/src/gtest-all.cc' object='src/testing/gtest/src/src_processor_test_assembler_unittest-gtest-all.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_processor_test_assembler_unittest-gtest-all.o `test -f 'src/testing/gtest/src/gtest-all.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest-all.cc + +src/testing/gtest/src/src_processor_test_assembler_unittest-gtest-all.obj: src/testing/gtest/src/gtest-all.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_processor_test_assembler_unittest-gtest-all.obj -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_processor_test_assembler_unittest-gtest-all.Tpo -c -o src/testing/gtest/src/src_processor_test_assembler_unittest-gtest-all.obj `if test -f 'src/testing/gtest/src/gtest-all.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest-all.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) src/testing/gtest/src/$(DEPDIR)/src_processor_test_assembler_unittest-gtest-all.Tpo src/testing/gtest/src/$(DEPDIR)/src_processor_test_assembler_unittest-gtest-all.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/gtest/src/gtest-all.cc' object='src/testing/gtest/src/src_processor_test_assembler_unittest-gtest-all.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_processor_test_assembler_unittest-gtest-all.obj `if test -f 'src/testing/gtest/src/gtest-all.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest-all.cc'; fi` + +src/testing/gtest/src/src_processor_test_assembler_unittest-gtest_main.o: src/testing/gtest/src/gtest_main.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_processor_test_assembler_unittest-gtest_main.o -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_processor_test_assembler_unittest-gtest_main.Tpo -c -o src/testing/gtest/src/src_processor_test_assembler_unittest-gtest_main.o `test -f 'src/testing/gtest/src/gtest_main.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest_main.cc +@am__fastdepCXX_TRUE@ $(am__mv) src/testing/gtest/src/$(DEPDIR)/src_processor_test_assembler_unittest-gtest_main.Tpo src/testing/gtest/src/$(DEPDIR)/src_processor_test_assembler_unittest-gtest_main.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/gtest/src/gtest_main.cc' object='src/testing/gtest/src/src_processor_test_assembler_unittest-gtest_main.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_processor_test_assembler_unittest-gtest_main.o `test -f 'src/testing/gtest/src/gtest_main.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest_main.cc + +src/testing/gtest/src/src_processor_test_assembler_unittest-gtest_main.obj: src/testing/gtest/src/gtest_main.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_processor_test_assembler_unittest-gtest_main.obj -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_processor_test_assembler_unittest-gtest_main.Tpo -c -o src/testing/gtest/src/src_processor_test_assembler_unittest-gtest_main.obj `if test -f 'src/testing/gtest/src/gtest_main.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest_main.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest_main.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) src/testing/gtest/src/$(DEPDIR)/src_processor_test_assembler_unittest-gtest_main.Tpo src/testing/gtest/src/$(DEPDIR)/src_processor_test_assembler_unittest-gtest_main.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/gtest/src/gtest_main.cc' object='src/testing/gtest/src/src_processor_test_assembler_unittest-gtest_main.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_processor_test_assembler_unittest-gtest_main.obj `if test -f 'src/testing/gtest/src/gtest_main.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest_main.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest_main.cc'; fi` + +src/testing/src/src_processor_test_assembler_unittest-gmock-all.o: src/testing/src/gmock-all.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/src/src_processor_test_assembler_unittest-gmock-all.o -MD -MP -MF src/testing/src/$(DEPDIR)/src_processor_test_assembler_unittest-gmock-all.Tpo -c -o src/testing/src/src_processor_test_assembler_unittest-gmock-all.o `test -f 'src/testing/src/gmock-all.cc' || echo '$(srcdir)/'`src/testing/src/gmock-all.cc +@am__fastdepCXX_TRUE@ $(am__mv) src/testing/src/$(DEPDIR)/src_processor_test_assembler_unittest-gmock-all.Tpo src/testing/src/$(DEPDIR)/src_processor_test_assembler_unittest-gmock-all.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/src/gmock-all.cc' object='src/testing/src/src_processor_test_assembler_unittest-gmock-all.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/src/src_processor_test_assembler_unittest-gmock-all.o `test -f 'src/testing/src/gmock-all.cc' || echo '$(srcdir)/'`src/testing/src/gmock-all.cc + +src/testing/src/src_processor_test_assembler_unittest-gmock-all.obj: src/testing/src/gmock-all.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/src/src_processor_test_assembler_unittest-gmock-all.obj -MD -MP -MF src/testing/src/$(DEPDIR)/src_processor_test_assembler_unittest-gmock-all.Tpo -c -o src/testing/src/src_processor_test_assembler_unittest-gmock-all.obj `if test -f 'src/testing/src/gmock-all.cc'; then $(CYGPATH_W) 'src/testing/src/gmock-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/src/gmock-all.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) src/testing/src/$(DEPDIR)/src_processor_test_assembler_unittest-gmock-all.Tpo src/testing/src/$(DEPDIR)/src_processor_test_assembler_unittest-gmock-all.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/src/gmock-all.cc' object='src/testing/src/src_processor_test_assembler_unittest-gmock-all.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/src/src_processor_test_assembler_unittest-gmock-all.obj `if test -f 'src/testing/src/gmock-all.cc'; then $(CYGPATH_W) 'src/testing/src/gmock-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/src/gmock-all.cc'; fi` + +src/processor/src_processor_test_assembler_unittest-test_assembler.o: src/processor/test_assembler.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_test_assembler_unittest-test_assembler.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_test_assembler_unittest-test_assembler.Tpo -c -o src/processor/src_processor_test_assembler_unittest-test_assembler.o `test -f 'src/processor/test_assembler.cc' || echo '$(srcdir)/'`src/processor/test_assembler.cc +@am__fastdepCXX_TRUE@ $(am__mv) src/processor/$(DEPDIR)/src_processor_test_assembler_unittest-test_assembler.Tpo src/processor/$(DEPDIR)/src_processor_test_assembler_unittest-test_assembler.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/processor/test_assembler.cc' object='src/processor/src_processor_test_assembler_unittest-test_assembler.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_test_assembler_unittest-test_assembler.o `test -f 'src/processor/test_assembler.cc' || echo '$(srcdir)/'`src/processor/test_assembler.cc + +src/processor/src_processor_test_assembler_unittest-test_assembler.obj: src/processor/test_assembler.cc +@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_test_assembler_unittest-test_assembler.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_test_assembler_unittest-test_assembler.Tpo -c -o src/processor/src_processor_test_assembler_unittest-test_assembler.obj `if test -f 'src/processor/test_assembler.cc'; then $(CYGPATH_W) 'src/processor/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/test_assembler.cc'; fi` +@am__fastdepCXX_TRUE@ $(am__mv) src/processor/$(DEPDIR)/src_processor_test_assembler_unittest-test_assembler.Tpo src/processor/$(DEPDIR)/src_processor_test_assembler_unittest-test_assembler.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/processor/test_assembler.cc' object='src/processor/src_processor_test_assembler_unittest-test_assembler.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_test_assembler_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_test_assembler_unittest-test_assembler.obj `if test -f 'src/processor/test_assembler.cc'; then $(CYGPATH_W) 'src/processor/test_assembler.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/test_assembler.cc'; fi` + mostlyclean-libtool: -rm -f *.lo diff --git a/src/processor/minidump_unittest.cc b/src/processor/minidump_unittest.cc index 93df5cc2..afbc4879 100644 --- a/src/processor/minidump_unittest.cc +++ b/src/processor/minidump_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009, Google Inc. +// Copyright (c) 2010, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -30,20 +30,39 @@ // Unit test for Minidump. Uses a pre-generated minidump and // verifies that certain streams are correct. -#include #include #include #include +#include #include #include #include "breakpad_googletest_includes.h" #include "google_breakpad/common/minidump_format.h" #include "google_breakpad/processor/minidump.h" #include "processor/logging.h" +#include "processor/synth_minidump.h" namespace { using google_breakpad::Minidump; +using google_breakpad::MinidumpContext; +using google_breakpad::MinidumpMemoryList; +using google_breakpad::MinidumpMemoryRegion; +using google_breakpad::MinidumpModule; +using google_breakpad::MinidumpModuleList; +using google_breakpad::MinidumpSystemInfo; +using google_breakpad::MinidumpThread; +using google_breakpad::MinidumpThreadList; +using google_breakpad::SynthMinidump::Context; +using google_breakpad::SynthMinidump::Dump; +using google_breakpad::SynthMinidump::Memory; +using google_breakpad::SynthMinidump::Module; +using google_breakpad::SynthMinidump::Stream; +using google_breakpad::SynthMinidump::String; +using google_breakpad::SynthMinidump::SystemInfo; +using google_breakpad::SynthMinidump::Thread; +using google_breakpad::TestAssembler::kBigEndian; +using google_breakpad::TestAssembler::kLittleEndian; using std::ifstream; using std::istringstream; using std::string; @@ -95,9 +114,421 @@ TEST_F(MinidumpTest, TestMinidumpFromStream) { //TODO: add more checks here } -} // namespace - -int main(int argc, char* argv[]) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); +TEST(Dump, ReadBackEmpty) { + Dump dump(0); + dump.Finish(); + string contents; + ASSERT_TRUE(dump.GetContents(&contents)); + istringstream stream(contents); + Minidump minidump(stream); + ASSERT_TRUE(minidump.Read()); + ASSERT_EQ(0U, minidump.GetDirectoryEntryCount()); } + +TEST(Dump, ReadBackEmptyBigEndian) { + Dump big_minidump(0, kBigEndian); + big_minidump.Finish(); + string contents; + ASSERT_TRUE(big_minidump.GetContents(&contents)); + istringstream stream(contents); + Minidump minidump(stream); + ASSERT_TRUE(minidump.Read()); + ASSERT_EQ(0U, minidump.GetDirectoryEntryCount()); +} + +TEST(Dump, OneStream) { + Dump dump(0, kBigEndian); + Stream stream(dump, 0xfbb7fa2bU); + stream.Append("stream contents"); + dump.Add(&stream); + dump.Finish(); + + string contents; + ASSERT_TRUE(dump.GetContents(&contents)); + istringstream minidump_stream(contents); + Minidump minidump(minidump_stream); + ASSERT_TRUE(minidump.Read()); + ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); + + const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0); + ASSERT_TRUE(dir != NULL); + EXPECT_EQ(0xfbb7fa2bU, dir->stream_type); + + u_int32_t stream_length; + ASSERT_TRUE(minidump.SeekToStreamType(0xfbb7fa2bU, &stream_length)); + ASSERT_EQ(15U, stream_length); + char stream_contents[15]; + ASSERT_TRUE(minidump.ReadBytes(stream_contents, sizeof(stream_contents))); + EXPECT_EQ(string("stream contents"), + string(stream_contents, sizeof(stream_contents))); + + EXPECT_FALSE(minidump.GetThreadList()); + EXPECT_FALSE(minidump.GetModuleList()); + EXPECT_FALSE(minidump.GetMemoryList()); + EXPECT_FALSE(minidump.GetException()); + EXPECT_FALSE(minidump.GetAssertion()); + EXPECT_FALSE(minidump.GetSystemInfo()); + EXPECT_FALSE(minidump.GetMiscInfo()); + EXPECT_FALSE(minidump.GetBreakpadInfo()); +} + +TEST(Dump, OneMemory) { + Dump dump(0, kBigEndian); + Memory memory(dump, 0x309d68010bd21b2cULL); + memory.Append("memory contents"); + dump.Add(&memory); + dump.Finish(); + + string contents; + ASSERT_TRUE(dump.GetContents(&contents)); + istringstream minidump_stream(contents); + Minidump minidump(minidump_stream); + ASSERT_TRUE(minidump.Read()); + ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); + + const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0); + ASSERT_TRUE(dir != NULL); + EXPECT_EQ((u_int32_t) MD_MEMORY_LIST_STREAM, dir->stream_type); + + MinidumpMemoryList *memory_list = minidump.GetMemoryList(); + ASSERT_TRUE(memory_list != NULL); + ASSERT_EQ(1U, memory_list->region_count()); + + MinidumpMemoryRegion *region1 = memory_list->GetMemoryRegionAtIndex(0); + ASSERT_EQ(0x309d68010bd21b2cULL, region1->GetBase()); + ASSERT_EQ(15U, region1->GetSize()); + const u_int8_t *region1_bytes = region1->GetMemory(); + ASSERT_TRUE(memcmp("memory contents", region1_bytes, 15) == 0); +} + +// One thread --- and its requisite entourage. +TEST(Dump, OneThread) { + Dump dump(0, kLittleEndian); + Memory stack(dump, 0x2326a0fa); + stack.Append("stack for thread"); + + MDRawContextX86 raw_context; + raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL; + raw_context.edi = 0x3ecba80d; + raw_context.esi = 0x382583b9; + raw_context.ebx = 0x7fccc03f; + raw_context.edx = 0xf62f8ec2; + raw_context.ecx = 0x46a6a6a8; + raw_context.eax = 0x6a5025e2; + raw_context.ebp = 0xd9fabb4a; + raw_context.eip = 0x6913f540; + raw_context.cs = 0xbffe6eda; + raw_context.eflags = 0xb2ce1e2d; + raw_context.esp = 0x659caaa4; + raw_context.ss = 0x2e951ef7; + Context context(dump, raw_context); + + Thread thread(dump, 0xa898f11b, stack, context, + 0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL); + + dump.Add(&stack); + dump.Add(&context); + dump.Add(&thread); + dump.Finish(); + + string contents; + ASSERT_TRUE(dump.GetContents(&contents)); + + istringstream minidump_stream(contents); + Minidump minidump(minidump_stream); + ASSERT_TRUE(minidump.Read()); + ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); + + MinidumpMemoryList *md_memory_list = minidump.GetMemoryList(); + ASSERT_TRUE(md_memory_list != NULL); + ASSERT_EQ(1U, md_memory_list->region_count()); + + MinidumpMemoryRegion *md_region = md_memory_list->GetMemoryRegionAtIndex(0); + ASSERT_EQ(0x2326a0faU, md_region->GetBase()); + ASSERT_EQ(16U, md_region->GetSize()); + const u_int8_t *region_bytes = md_region->GetMemory(); + ASSERT_TRUE(memcmp("stack for thread", region_bytes, 16) == 0); + + MinidumpThreadList *thread_list = minidump.GetThreadList(); + ASSERT_TRUE(thread_list != NULL); + ASSERT_EQ(1U, thread_list->thread_count()); + + MinidumpThread *md_thread = thread_list->GetThreadAtIndex(0); + ASSERT_TRUE(md_thread != NULL); + u_int32_t thread_id; + ASSERT_TRUE(md_thread->GetThreadID(&thread_id)); + ASSERT_EQ(0xa898f11bU, thread_id); + MinidumpMemoryRegion *md_stack = md_thread->GetMemory(); + ASSERT_TRUE(md_stack != NULL); + ASSERT_EQ(0x2326a0faU, md_stack->GetBase()); + ASSERT_EQ(16U, md_stack->GetSize()); + const u_int8_t *md_stack_bytes = md_stack->GetMemory(); + ASSERT_TRUE(memcmp("stack for thread", md_stack_bytes, 16) == 0); + + MinidumpContext *md_context = md_thread->GetContext(); + ASSERT_TRUE(md_context != NULL); + ASSERT_EQ((u_int32_t) MD_CONTEXT_X86, md_context->GetContextCPU()); + const MDRawContextX86 *md_raw_context = md_context->GetContextX86(); + ASSERT_TRUE(md_raw_context != NULL); + ASSERT_EQ((u_int32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL), + (md_raw_context->context_flags + & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL))); + EXPECT_EQ(0x3ecba80dU, raw_context.edi); + EXPECT_EQ(0x382583b9U, raw_context.esi); + EXPECT_EQ(0x7fccc03fU, raw_context.ebx); + EXPECT_EQ(0xf62f8ec2U, raw_context.edx); + EXPECT_EQ(0x46a6a6a8U, raw_context.ecx); + EXPECT_EQ(0x6a5025e2U, raw_context.eax); + EXPECT_EQ(0xd9fabb4aU, raw_context.ebp); + EXPECT_EQ(0x6913f540U, raw_context.eip); + EXPECT_EQ(0xbffe6edaU, raw_context.cs); + EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags); + EXPECT_EQ(0x659caaa4U, raw_context.esp); + EXPECT_EQ(0x2e951ef7U, raw_context.ss); +} + +TEST(Dump, OneModule) { + static const MDVSFixedFileInfo fixed_file_info = { + 0xb2fba33a, // signature + 0x33d7a728, // struct_version + 0x31afcb20, // file_version_hi + 0xe51cdab1, // file_version_lo + 0xd1ea6907, // product_version_hi + 0x03032857, // product_version_lo + 0x11bf71d7, // file_flags_mask + 0x5fb8cdbf, // file_flags + 0xe45d0d5d, // file_os + 0x107d9562, // file_type + 0x5a8844d4, // file_subtype + 0xa8d30b20, // file_date_hi + 0x651c3e4e // file_date_lo + }; + + Dump dump(0, kBigEndian); + String module_name(dump, "single module"); + Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd, + module_name, + 0xb1054d2a, + 0x34571371, + fixed_file_info, // from synth_minidump_unittest_data.h + NULL, NULL); + + dump.Add(&module); + dump.Add(&module_name); + dump.Finish(); + + string contents; + ASSERT_TRUE(dump.GetContents(&contents)); + istringstream minidump_stream(contents); + Minidump minidump(minidump_stream); + ASSERT_TRUE(minidump.Read()); + ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); + + const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0); + ASSERT_TRUE(dir != NULL); + EXPECT_EQ((u_int32_t) MD_MODULE_LIST_STREAM, dir->stream_type); + + MinidumpModuleList *md_module_list = minidump.GetModuleList(); + ASSERT_TRUE(md_module_list != NULL); + ASSERT_EQ(1U, md_module_list->module_count()); + + const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0); + ASSERT_TRUE(md_module != NULL); + ASSERT_EQ(0xa90206ca83eb2852ULL, md_module->base_address()); + ASSERT_EQ(0xada542bd, md_module->size()); + ASSERT_EQ("single module", md_module->code_file()); + + const MDRawModule *md_raw_module = md_module->module(); + ASSERT_TRUE(md_raw_module != NULL); + ASSERT_EQ(0xb1054d2aU, md_raw_module->time_date_stamp); + ASSERT_EQ(0x34571371U, md_raw_module->checksum); + ASSERT_TRUE(memcmp(&md_raw_module->version_info, &fixed_file_info, + sizeof(fixed_file_info)) == 0); +} + +TEST(Dump, OneSystemInfo) { + Dump dump(0, kLittleEndian); + String csd_version(dump, "Petulant Pierogi"); + SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version); + + dump.Add(&system_info); + dump.Add(&csd_version); + dump.Finish(); + + string contents; + ASSERT_TRUE(dump.GetContents(&contents)); + istringstream minidump_stream(contents); + Minidump minidump(minidump_stream); + ASSERT_TRUE(minidump.Read()); + ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); + + const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0); + ASSERT_TRUE(dir != NULL); + EXPECT_EQ((u_int32_t) MD_SYSTEM_INFO_STREAM, dir->stream_type); + + MinidumpSystemInfo *md_system_info = minidump.GetSystemInfo(); + ASSERT_TRUE(md_system_info != NULL); + ASSERT_EQ("windows", md_system_info->GetOS()); + ASSERT_EQ("x86", md_system_info->GetCPU()); + ASSERT_EQ("Petulant Pierogi", *md_system_info->GetCSDVersion()); + ASSERT_EQ("GenuineIntel", *md_system_info->GetCPUVendor()); +} + +TEST(Dump, BigDump) { + Dump dump(0, kLittleEndian); + + // A SystemInfo stream. + String csd_version(dump, "Munificent Macaque"); + SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version); + dump.Add(&csd_version); + dump.Add(&system_info); + + // Five threads! + Memory stack0(dump, 0x70b9ebfc); + stack0.Append("stack for thread zero"); + MDRawContextX86 raw_context0; + raw_context0.context_flags = MD_CONTEXT_X86_INTEGER; + raw_context0.eip = 0xaf0709e4; + Context context0(dump, raw_context0); + Thread thread0(dump, 0xbbef4432, stack0, context0, + 0xd0377e7b, 0xdb8eb0cf, 0xd73bc314, 0x09d357bac7f9a163ULL); + dump.Add(&stack0); + dump.Add(&context0); + dump.Add(&thread0); + + Memory stack1(dump, 0xf988cc45); + stack1.Append("stack for thread one"); + MDRawContextX86 raw_context1; + raw_context1.context_flags = MD_CONTEXT_X86_INTEGER; + raw_context1.eip = 0xe4f56f81; + Context context1(dump, raw_context1); + Thread thread1(dump, 0x657c3f58, stack1, context1, + 0xa68fa182, 0x6f3cf8dd, 0xe3a78ccf, 0x78cc84775e4534bbULL); + dump.Add(&stack1); + dump.Add(&context1); + dump.Add(&thread1); + + Memory stack2(dump, 0xc8a92e7c); + stack2.Append("stack for thread two"); + MDRawContextX86 raw_context2; + raw_context2.context_flags = MD_CONTEXT_X86_INTEGER; + raw_context2.eip = 0xb336a438; + Context context2(dump, raw_context2); + Thread thread2(dump, 0xdf4b8a71, stack2, context2, + 0x674c26b6, 0x445d7120, 0x7e700c56, 0xd89bf778e7793e17ULL); + dump.Add(&stack2); + dump.Add(&context2); + dump.Add(&thread2); + + Memory stack3(dump, 0x36d08e08); + stack3.Append("stack for thread three"); + MDRawContextX86 raw_context3; + raw_context3.context_flags = MD_CONTEXT_X86_INTEGER; + raw_context3.eip = 0xdf99a60c; + Context context3(dump, raw_context3); + Thread thread3(dump, 0x86e6c341, stack3, context3, + 0x32dc5c55, 0x17a2aba8, 0xe0cc75e7, 0xa46393994dae83aeULL); + dump.Add(&stack3); + dump.Add(&context3); + dump.Add(&thread3); + + Memory stack4(dump, 0x1e0ab4fa); + stack4.Append("stack for thread four"); + MDRawContextX86 raw_context4; + raw_context4.context_flags = MD_CONTEXT_X86_INTEGER; + raw_context4.eip = 0xaa646267; + Context context4(dump, raw_context4); + Thread thread4(dump, 0x261a28d4, stack4, context4, + 0x6ebd389e, 0xa0cd4759, 0x30168846, 0x164f650a0cf39d35ULL); + dump.Add(&stack4); + dump.Add(&context4); + dump.Add(&thread4); + + // Three modules! + String module1_name(dump, "module one"); + Module module1(dump, 0xeb77da57b5d4cbdaULL, 0x83cd5a37, module1_name); + dump.Add(&module1_name); + dump.Add(&module1); + + String module2_name(dump, "module two"); + Module module2(dump, 0x8675884adfe5ac90ULL, 0xb11e4ea3, module2_name); + dump.Add(&module2_name); + dump.Add(&module2); + + String module3_name(dump, "module three"); + Module module3(dump, 0x95fc1544da321b6cULL, 0x7c2bf081, module3_name); + dump.Add(&module3_name); + dump.Add(&module3); + + // Add one more memory region, on top of the five stacks. + Memory memory5(dump, 0x61979e828040e564ULL); + memory5.Append("contents of memory 5"); + dump.Add(&memory5); + + dump.Finish(); + + string contents; + ASSERT_TRUE(dump.GetContents(&contents)); + istringstream minidump_stream(contents); + Minidump minidump(minidump_stream); + ASSERT_TRUE(minidump.Read()); + ASSERT_EQ(4U, minidump.GetDirectoryEntryCount()); + + // Check the threads. + MinidumpThreadList *thread_list = minidump.GetThreadList(); + ASSERT_TRUE(thread_list != NULL); + ASSERT_EQ(5U, thread_list->thread_count()); + u_int32_t thread_id; + ASSERT_TRUE(thread_list->GetThreadAtIndex(0)->GetThreadID(&thread_id)); + ASSERT_EQ(0xbbef4432U, thread_id); + ASSERT_EQ(0x70b9ebfcU, + thread_list->GetThreadAtIndex(0)->GetMemory()->GetBase()); + ASSERT_EQ(0xaf0709e4U, + thread_list->GetThreadAtIndex(0)->GetContext()->GetContextX86() + ->eip); + + ASSERT_TRUE(thread_list->GetThreadAtIndex(1)->GetThreadID(&thread_id)); + ASSERT_EQ(0x657c3f58U, thread_id); + ASSERT_EQ(0xf988cc45U, + thread_list->GetThreadAtIndex(1)->GetMemory()->GetBase()); + ASSERT_EQ(0xe4f56f81U, + thread_list->GetThreadAtIndex(1)->GetContext()->GetContextX86() + ->eip); + + ASSERT_TRUE(thread_list->GetThreadAtIndex(2)->GetThreadID(&thread_id)); + ASSERT_EQ(0xdf4b8a71U, thread_id); + ASSERT_EQ(0xc8a92e7cU, + thread_list->GetThreadAtIndex(2)->GetMemory()->GetBase()); + ASSERT_EQ(0xb336a438U, + thread_list->GetThreadAtIndex(2)->GetContext()->GetContextX86() + ->eip); + + ASSERT_TRUE(thread_list->GetThreadAtIndex(3)->GetThreadID(&thread_id)); + ASSERT_EQ(0x86e6c341U, thread_id); + ASSERT_EQ(0x36d08e08U, + thread_list->GetThreadAtIndex(3)->GetMemory()->GetBase()); + ASSERT_EQ(0xdf99a60cU, + thread_list->GetThreadAtIndex(3)->GetContext()->GetContextX86() + ->eip); + + ASSERT_TRUE(thread_list->GetThreadAtIndex(4)->GetThreadID(&thread_id)); + ASSERT_EQ(0x261a28d4U, thread_id); + ASSERT_EQ(0x1e0ab4faU, + thread_list->GetThreadAtIndex(4)->GetMemory()->GetBase()); + ASSERT_EQ(0xaa646267U, + thread_list->GetThreadAtIndex(4)->GetContext()->GetContextX86() + ->eip); + + // Check the modules. + MinidumpModuleList *md_module_list = minidump.GetModuleList(); + ASSERT_TRUE(md_module_list != NULL); + ASSERT_EQ(3U, md_module_list->module_count()); + EXPECT_EQ(0xeb77da57b5d4cbdaULL, + md_module_list->GetModuleAtIndex(0)->base_address()); + EXPECT_EQ(0x8675884adfe5ac90ULL, + md_module_list->GetModuleAtIndex(1)->base_address()); + EXPECT_EQ(0x95fc1544da321b6cULL, + md_module_list->GetModuleAtIndex(2)->base_address()); +} + +} // namespace diff --git a/src/processor/synth_minidump.cc b/src/processor/synth_minidump.cc new file mode 100644 index 00000000..c25d421f --- /dev/null +++ b/src/processor/synth_minidump.cc @@ -0,0 +1,309 @@ +// Copyright (c) 2010, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Original author: Jim Blandy + +// synth_minidump.cc: Implementation of SynthMinidump. See synth_minidump.h + +#include "processor/synth_minidump.h" + +namespace google_breakpad { + +namespace SynthMinidump { + +Section::Section(const Dump &dump) + : TestAssembler::Section(dump.endianness()) { } + +void Section::CiteLocationIn(TestAssembler::Section *section) const { + if (this) + (*section).D32(size_).D32(file_offset_); + else + (*section).D32(0).D32(0); +} + +void Stream::CiteStreamIn(TestAssembler::Section *section) const { + section->D32(type_); + CiteLocationIn(section); +} + +SystemInfo::SystemInfo(const Dump &dump, + const MDRawSystemInfo &system_info, + const String &csd_version) + : Stream(dump, MD_SYSTEM_INFO_STREAM) { + D16(system_info.processor_architecture); + D16(system_info.processor_level); + D16(system_info.processor_revision); + D8(system_info.number_of_processors); + D8(system_info.product_type); + D32(system_info.major_version); + D32(system_info.minor_version); + D32(system_info.build_number); + D32(system_info.platform_id); + csd_version.CiteStringIn(this); + D16(system_info.suite_mask); + D16(system_info.reserved2); // Well, why not? + + // MDCPUInformation cpu; + if (system_info.processor_architecture == MD_CPU_ARCHITECTURE_X86) { + D32(system_info.cpu.x86_cpu_info.vendor_id[0]); + D32(system_info.cpu.x86_cpu_info.vendor_id[1]); + D32(system_info.cpu.x86_cpu_info.vendor_id[2]); + D32(system_info.cpu.x86_cpu_info.version_information); + D32(system_info.cpu.x86_cpu_info.feature_information); + D32(system_info.cpu.x86_cpu_info.amd_extended_cpu_features); + } else { + D64(system_info.cpu.other_cpu_info.processor_features[0]); + D64(system_info.cpu.other_cpu_info.processor_features[1]); + } +} + +const MDRawSystemInfo SystemInfo::windows_x86 = { + MD_CPU_ARCHITECTURE_X86, // processor_architecture + 6, // processor_level + 0xd08, // processor_revision + 1, // number_of_processors + 1, // product_type + 5, // major_version + 1, // minor_version + 2600, // build_number + 2, // platform_id + 0xdeadbeef, // csd_version_rva + 0x100, // suite_mask + 0, // reserved2 + { // cpu + { // x86_cpu_info + { 0x756e6547, 0x49656e69, 0x6c65746e }, // vendor_id + 0x6d8, // version_information + 0xafe9fbff, // feature_information + 0xffffffff // amd_extended_cpu_features + } + } +}; + +const string SystemInfo::windows_x86_csd_version = "Service Pack 2"; + +String::String(const Dump &dump, const string &contents) : Section(dump) { + D32(contents.size() * 2); + for (string::const_iterator i = contents.begin(); i != contents.end(); i++) + D16(*i); +} + +void String::CiteStringIn(TestAssembler::Section *section) const { + section->D32(file_offset_); +} + +void Memory::CiteMemoryIn(TestAssembler::Section *section) const { + section->D64(address_); + CiteLocationIn(section); +} + +Context::Context(const Dump &dump, const MDRawContextX86 &context) + : Section(dump) { + // The caller should have properly set the CPU type flag. + assert(context.context_flags & MD_CONTEXT_X86); + // It doesn't make sense to store x86 registers in big-endian form. + assert(dump.endianness() == kLittleEndian); + D32(context.context_flags); + D32(context.dr0); + D32(context.dr1); + D32(context.dr2); + D32(context.dr3); + D32(context.dr6); + D32(context.dr7); + D32(context.float_save.control_word); + D32(context.float_save.status_word); + D32(context.float_save.tag_word); + D32(context.float_save.error_offset); + D32(context.float_save.error_selector); + D32(context.float_save.data_offset); + D32(context.float_save.data_selector); + // context.float_save.register_area[] contains 8-bit quantities and + // does not need to be swapped. + Append(context.float_save.register_area, + sizeof(context.float_save.register_area)); + D32(context.float_save.cr0_npx_state); + D32(context.gs); + D32(context.fs); + D32(context.es); + D32(context.ds); + D32(context.edi); + D32(context.esi); + D32(context.ebx); + D32(context.edx); + D32(context.ecx); + D32(context.eax); + D32(context.ebp); + D32(context.eip); + D32(context.cs); + D32(context.eflags); + D32(context.esp); + D32(context.ss); + // context.extended_registers[] contains 8-bit quantities and does + // not need to be swapped. + Append(context.extended_registers, sizeof(context.extended_registers)); + assert(Size() == sizeof(MDRawContextX86)); +} + +Thread::Thread(const Dump &dump, + u_int32_t thread_id, const Memory &stack, const Context &context, + u_int32_t suspend_count, u_int32_t priority_class, + u_int32_t priority, u_int64_t teb) : Section(dump) { + D32(thread_id); + D32(suspend_count); + D32(priority_class); + D32(priority); + D64(teb); + stack.CiteMemoryIn(this); + context.CiteLocationIn(this); + assert(Size() == sizeof(MDRawThread)); +} + +Module::Module(const Dump &dump, + u_int64_t base_of_image, + u_int32_t size_of_image, + const String &name, + u_int32_t time_date_stamp, + u_int32_t checksum, + const MDVSFixedFileInfo &version_info, + const Section *cv_record, + const Section *misc_record) : Section(dump) { + D64(base_of_image); + D32(size_of_image); + D32(checksum); + D32(time_date_stamp); + name.CiteStringIn(this); + D32(version_info.signature); + D32(version_info.struct_version); + D32(version_info.file_version_hi); + D32(version_info.file_version_lo); + D32(version_info.product_version_hi); + D32(version_info.product_version_lo); + D32(version_info.file_flags_mask); + D32(version_info.file_flags); + D32(version_info.file_os); + D32(version_info.file_type); + D32(version_info.file_subtype); + D32(version_info.file_date_hi); + D32(version_info.file_date_lo); + cv_record->CiteLocationIn(this); + misc_record->CiteLocationIn(this); + D64(0).D64(0); +} + +const MDVSFixedFileInfo Module::stock_version_info = { + MD_VSFIXEDFILEINFO_SIGNATURE, // signature + MD_VSFIXEDFILEINFO_VERSION, // struct_version + 0x11111111, // file_version_hi + 0x22222222, // file_version_lo + 0x33333333, // product_version_hi + 0x44444444, // product_version_lo + MD_VSFIXEDFILEINFO_FILE_FLAGS_DEBUG, // file_flags_mask + MD_VSFIXEDFILEINFO_FILE_FLAGS_DEBUG, // file_flags + MD_VSFIXEDFILEINFO_FILE_OS_NT | MD_VSFIXEDFILEINFO_FILE_OS__WINDOWS32, + // file_os + MD_VSFIXEDFILEINFO_FILE_TYPE_APP, // file_type + MD_VSFIXEDFILEINFO_FILE_SUBTYPE_UNKNOWN, // file_subtype + 0, // file_date_hi + 0 // file_date_lo +}; + +Dump::Dump(u_int64_t flags, + Endianness endianness, + u_int32_t version, + u_int32_t date_time_stamp) + : TestAssembler::Section(endianness), + file_start_(0), + stream_directory_(*this), + stream_count_(0), + thread_list_(*this, MD_THREAD_LIST_STREAM), + module_list_(*this, MD_MODULE_LIST_STREAM), + memory_list_(*this, MD_MEMORY_LIST_STREAM) + { + D32(MD_HEADER_SIGNATURE); + D32(version); + D32(stream_count_label_); + D32(stream_directory_rva_); + D32(0); + D32(date_time_stamp); + D64(flags); + assert(Size() == sizeof(MDRawHeader)); +} + +Dump &Dump::Add(SynthMinidump::Section *section) { + section->Finish(file_start_ + Size()); + Append(*section); + return *this; +} + +Dump &Dump::Add(Stream *stream) { + Add(static_cast(stream)); + stream->CiteStreamIn(&stream_directory_); + stream_count_++; + return *this; +} + +Dump &Dump::Add(Memory *memory) { + // Add the memory contents themselves to the file. + Add(static_cast(memory)); + + // The memory list is a list of MDMemoryDescriptors, not of actual + // memory elements. Produce a descriptor, and add that to the list. + SynthMinidump::Section descriptor(*this); + memory->CiteMemoryIn(&descriptor); + memory_list_.Add(&descriptor); + return *this; +} + +Dump &Dump::Add(Thread *thread) { + thread_list_.Add(thread); + return *this; +} + +Dump &Dump::Add(Module *module) { + module_list_.Add(module); + return *this; +} + +void Dump::Finish() { + if (!thread_list_.Empty()) Add(&thread_list_); + if (!module_list_.Empty()) Add(&module_list_); + if (!memory_list_.Empty()) Add(&memory_list_); + + // Create the stream directory. We don't use + // stream_directory_.Finish here, because the stream directory isn't + // cited using a location descriptor; rather, the Minidump header + // has the stream count and MDRVA. + stream_count_label_ = stream_count_; + stream_directory_rva_ = file_start_ + Size(); + Append(static_cast(stream_directory_)); +} + +} // namespace SynthMinidump + +} // namespace google_breakpad diff --git a/src/processor/synth_minidump.h b/src/processor/synth_minidump.h new file mode 100644 index 00000000..28677805 --- /dev/null +++ b/src/processor/synth_minidump.h @@ -0,0 +1,357 @@ +// -*- mode: C++ -*- + +// Copyright (c) 2010, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Original author: Jim Blandy + +// synth_minidump.h: Interface to SynthMinidump: fake minidump generator. +// +// We treat a minidump file as the concatenation of a bunch of +// TestAssembler::Sections. The file header, stream directory, +// streams, memory regions, strings, and so on --- each is a Section +// that eventually gets appended to the minidump. Dump, Memory, +// Context, Thread, and so on all inherit from TestAssembler::Section. +// For example: +// +// using google_breakpad::TestAssembler::kLittleEndian; +// using google_breakpad::SynthMinidump::Context; +// using google_breakpad::SynthMinidump::Dump; +// using google_breakpad::SynthMinidump::Memory; +// using google_breakpad::SynthMinidump::Thread; +// +// Dump minidump(MD_NORMAL, kLittleEndian); +// +// Memory stack1(minidump, 0x569eb0a9); +// ... build contents of stack1 with TestAssembler::Section functions ... +// +// MDRawContextX86 x86_context1; +// x86_context1.context_flags = MD_CONTEXT_X86; +// x86_context1.eip = 0x7c90eb94; +// x86_context1.esp = 0x569eb0a9; +// x86_context1.ebp = x86_context1.esp + something appropriate; +// Context context1(minidump, x86_context1); +// +// Thread thread1(minidump, 0xe4a4821d, stack1, context1); +// +// minidump.Add(&stack1); +// minidump.Add(&context1); +// minidump.Add(&thread1); +// minidump.Finish(); +// +// string contents; +// EXPECT_TRUE(minidump.GetContents(&contents)); +// // contents now holds the bytes of a minidump file +// +// Because the TestAssembler classes let us write Label references to +// sections before the Labels' values are known, this gives us +// flexibility in how we put the dump together: minidump pieces can +// hold the file offsets of other minidump pieces before the +// referents' positions have been decided. As long as everything has +// been placed by the time we call dump.GetContents to obtain the +// bytes, all the Labels' values will be known, and everything will +// get patched up appropriately. +// +// The dump.Add(thing) functions append THINGS's contents to the +// minidump, but they also do two other things: +// +// - dump.Add(thing) invokes thing->Finish, which tells *thing the +// offset within the file at which it was placed, and allows *thing +// to do any final content generation. +// +// - If THING is something which should receive an entry in some sort +// of list or directory, then dump.Add(THING) automatically creates +// the appropriate directory or list entry. Streams must appear in +// the stream directory; memory ranges should be listed in the +// memory list; threads should be placed in the thread list; and so +// on. +// +// By convention, Section subclass constructors that take references +// to other Sections do not take care of 'Add'ing their arguments to +// the dump. For example, although the Thread constructor takes +// references to a Memory and a Context, it does not add them to the +// dump on the caller's behalf. Rather, the caller is responsible for +// 'Add'ing every section they create. This allows Sections to be +// cited from more than one place; for example, Memory ranges are +// cited both from Thread objects (as their stack contents) and by the +// memory list stream. +// +// If you forget to Add some Section, the Dump::GetContents call will +// fail, as the TestAssembler::Labels used to cite the Section's +// contents from elsewhere will still be undefined. +#ifndef PROCESSOR_SYNTH_MINIDUMP_H_ +#define PROCESSOR_SYNTH_MINIDUMP_H_ + +#include +#include +#include + +#include "google_breakpad/common/breakpad_types.h" +#include "google_breakpad/common/minidump_format.h" +#include "processor/test_assembler.h" + +namespace google_breakpad { + +namespace SynthMinidump { + +using std::string; +using TestAssembler::Endianness; +using TestAssembler::kBigEndian; +using TestAssembler::kLittleEndian; +using TestAssembler::kUnsetEndian; +using TestAssembler::Label; + +class Dump; +class Memory; +class String; + +// A TestAssembler::Section which will be appended to a minidump. +class Section: public TestAssembler::Section { + public: + explicit Section(const Dump &dump); + + // Append an MDLocationDescriptor referring to this section to SECTION. + // If 'this' is NULL, append a descriptor with a zero length and MDRVA. + // + // (I couldn't find the language in the C++ standard that says that + // invoking member functions of a NULL pointer to a class type is + // bad, if such language exists. Having this function handle NULL + // 'this' is convenient, but if it causes trouble, it's not hard to + // do differently.) + void CiteLocationIn(TestAssembler::Section *section) const; + + // Note that this section's contents are complete, and that it has + // been placed in the minidump file at OFFSET. The 'Add' member + // functions call the Finish member function of the object being + // added for you; if you are 'Add'ing this section, you needn't Finish it. + virtual void Finish(const Label &offset) { + file_offset_ = offset; size_ = Size(); + } + + protected: + // This section's size and offset within the minidump file. + Label file_offset_, size_; +}; + +// A stream within a minidump file. 'Add'ing a stream to a minidump +// creates an entry for it in the minidump's stream directory. +class Stream: public Section { + public: + // Create a stream of type TYPE. You can append whatever contents + // you like to this stream using the TestAssembler::Section methods. + Stream(const Dump &dump, u_int32_t type) : Section(dump), type_(type) { } + + // Append an MDRawDirectory referring to this stream to SECTION. + void CiteStreamIn(TestAssembler::Section *section) const; + + private: + // The type of this stream. + u_int32_t type_; +}; + +class SystemInfo: public Stream { + public: + // Create an MD_SYSTEM_INFO_STREAM stream belonging to DUMP holding + // an MDRawSystem info structure initialized with the values from + // SYSTEM_INFO, except that the csd_version field is replaced with + // the file offset of the string CSD_VERSION, which can be 'Add'ed + // to the dump at the desired location. + // + // Remember that you are still responsible for 'Add'ing CSD_VERSION + // to the dump yourself. + SystemInfo(const Dump &dump, + const MDRawSystemInfo &system_info, + const String &csd_version); + + // Stock MDRawSystemInfo information and associated strings, for + // writing tests. + static const MDRawSystemInfo windows_x86; + static const string windows_x86_csd_version; +}; + +// An MDString: a string predeced by a 32-bit length. +class String: public Section { + public: + String(const Dump &dump, const string &value); + + // Append an MDRVA referring to this string to SECTION. + void CiteStringIn(TestAssembler::Section *section) const; +}; + +// A range of memory contents. 'Add'ing a memory range to a minidump +// creates n entry for it in the minidump's memory list. By +// convention, the 'start', 'Here', and 'Mark' member functions refer +// to memory addresses. +class Memory: public Section { + public: + Memory(const Dump &dump, u_int64_t address) + : Section(dump), address_(address) { start() = address; } + + // Append an MDMemoryDescriptor referring to this memory range to SECTION. + void CiteMemoryIn(TestAssembler::Section *section) const; + + private: + // The process address from which these memory contents were taken. + // Shouldn't this be a Label? + u_int64_t address_; +}; + +class Context: public Section { + public: + // Create a context belonging to DUMP whose contents are a copy of CONTEXT. + Context(const Dump &dump, const MDRawContextX86 &context); + // Add constructors for other architectures here. Remember to byteswap. +}; + +class Thread: public Section { + public: + // Create a thread belonging to DUMP with the given values, citing + // STACK and CONTEXT (which you must Add to the dump separately). + Thread(const Dump &dump, + u_int32_t thread_id, + const Memory &stack, + const Context &context, + u_int32_t suspend_count = 0, + u_int32_t priority_class = 0, + u_int32_t priority = 0, + u_int64_t teb = 0); +}; + +class Module: public Section { + public: + // Create a module with the given values. Note that CV_RECORD and + // MISC_RECORD can be NULL, in which case the corresponding location + // descriptior in the minidump will have a length of zero. + Module(const Dump &dump, + u_int64_t base_of_image, + u_int32_t size_of_image, + const String &name, + u_int32_t time_date_stamp = 1262805309, + u_int32_t checksum = 0, + const MDVSFixedFileInfo &version_info = Module::stock_version_info, + const Section *cv_record = NULL, + const Section *misc_record = NULL); + + private: + // A standard MDVSFixedFileInfo structure to use as a default for + // minidumps. There's no reason to make users write out all this crap + // over and over. + static const MDVSFixedFileInfo stock_version_info; +}; + +// A list of entries starting with a 32-bit count, like a memory list +// or a thread list. +template +class List: public Stream { + public: + List(const Dump &dump, u_int32_t type) : Stream(dump, type), count_(0) { + D32(count_label_); + } + + // Add ELEMENT to this list. + void Add(Element *element) { + element->Finish(file_offset_ + Size()); + Append(*element); + count_++; + } + + // Return true if this List is empty, false otherwise. + bool Empty() { return count_ == 0; } + + // Finish up the contents of this section, mark it as having been + // placed at OFFSET. + virtual void Finish(const Label &offset) { + Stream::Finish(offset); + count_label_ = count_; + } + + private: + size_t count_; + Label count_label_; +}; + +class Dump: public TestAssembler::Section { + public: + + // Create a TestAssembler::Section containing a minidump file whose + // header uses the given values. ENDIANNESS determines the + // endianness of the signature; we set this section's default + // endianness by this. + Dump(u_int64_t flags, + Endianness endianness = kLittleEndian, + u_int32_t version = MD_HEADER_VERSION, + u_int32_t date_time_stamp = 1262805309); + + // The following functions call OBJECT->Finish(), and append the + // contents of OBJECT to this minidump. They also record OBJECT in + // whatever directory or list is appropriate for its type. The + // stream directory, memory list, thread list, and module list are + // accumulated this way. + Dump &Add(SynthMinidump::Section *object); // simply append data + Dump &Add(Stream *object); // append, record in stream directory + Dump &Add(Memory *object); // append, record in memory list + Dump &Add(Thread *object); // append, record in thread list + Dump &Add(Module *object); // append, record in module list + + // Complete the construction of the minidump, given the Add calls + // we've seen up to this point. After this call, this Dump's + // contents are complete, all labels should be defined if everything + // Cited has been Added, and you may call GetContents on it. + void Finish(); + + private: + // A label representing the start of the minidump file. + Label file_start_; + + // The stream directory. We construct this incrementally from + // Add(Stream *) calls. + SynthMinidump::Section stream_directory_; // The directory's contents. + size_t stream_count_; // The number of streams so far. + Label stream_count_label_; // Cited in file header. + Label stream_directory_rva_; // The directory's file offset. + + // This minidump's thread list. We construct this incrementally from + // Add(Thread *) calls. + List thread_list_; + + // This minidump's module list. We construct this incrementally from + // Add(Module *) calls. + List module_list_; + + // This minidump's memory list. We construct this incrementally from + // Add(Memory *) calls. This is actually a list of MDMemoryDescriptors, + // not memory ranges --- thus the odd type. + List memory_list_; +}; + +} // namespace SynthMinidump + +} // namespace google_breakpad + +#endif // PROCESSOR_SYNTH_MINIDUMP_H_ diff --git a/src/processor/synth_minidump_unittest.cc b/src/processor/synth_minidump_unittest.cc new file mode 100644 index 00000000..755468d5 --- /dev/null +++ b/src/processor/synth_minidump_unittest.cc @@ -0,0 +1,280 @@ +// Copyright (c) 2010, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Original author: Jim Blandy + +// test_assembler_unittest.cc: Unit tests for google_breakpad::TestAssembler. + +#include +#include + +#include "breakpad_googletest_includes.h" +#include "google_breakpad/common/minidump_format.h" +#include "processor/synth_minidump.h" +#include "processor/synth_minidump_unittest_data.h" + +using google_breakpad::SynthMinidump::Context; +using google_breakpad::SynthMinidump::Dump; +using google_breakpad::SynthMinidump::List; +using google_breakpad::SynthMinidump::Memory; +using google_breakpad::SynthMinidump::Module; +using google_breakpad::SynthMinidump::Section; +using google_breakpad::SynthMinidump::Stream; +using google_breakpad::SynthMinidump::String; +using google_breakpad::SynthMinidump::SystemInfo; +using google_breakpad::SynthMinidump::Thread; +using google_breakpad::TestAssembler::kBigEndian; +using google_breakpad::TestAssembler::kLittleEndian; +using google_breakpad::TestAssembler::Label; +using std::string; + +TEST(Section, Simple) { + Dump dump(0); + Section section(dump); + section.L32(0x12345678); + section.Finish(0); + string contents; + ASSERT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\x78\x56\x34\x12", 4), contents); +} + +TEST(Section, CiteLocationIn) { + Dump dump(0, kBigEndian); + Section section1(dump), section2(dump); + section1.Append("order"); + section2.Append("mayhem"); + section2.Finish(0x32287ec2); + section2.CiteLocationIn(§ion1); + string contents; + ASSERT_TRUE(section1.GetContents(&contents)); + string expected("order\0\0\0\x06\x32\x28\x7e\xc2", 13); + EXPECT_EQ(expected, contents); +} + +TEST(Stream, CiteStreamIn) { + Dump dump(0, kLittleEndian); + Stream stream(dump, 0x40cae2b3); + Section section(dump); + stream.Append("stream contents"); + section.Append("section contents"); + stream.Finish(0x41424344); + stream.CiteStreamIn(§ion); + string contents; + ASSERT_TRUE(section.GetContents(&contents)); + string expected("section contents" + "\xb3\xe2\xca\x40" + "\x0f\0\0\0" + "\x44\x43\x42\x41", + 16 + 4 + 4 + 4); + EXPECT_EQ(expected, contents); +} + +TEST(Memory, CiteMemoryIn) { + Dump dump(0, kBigEndian); + Memory memory(dump, 0x76d010874ab019f9ULL); + Section section(dump); + memory.Append("memory contents"); + section.Append("section contents"); + memory.Finish(0x51525354); + memory.CiteMemoryIn(§ion); + string contents; + ASSERT_TRUE(section.GetContents(&contents)); + string expected("section contents" + "\x76\xd0\x10\x87\x4a\xb0\x19\xf9" + "\0\0\0\x0f" + "\x51\x52\x53\x54", + 16 + 8 + 4 + 4); + EXPECT_EQ(contents, expected); +} + +TEST(Memory, Here) { + Dump dump(0, kBigEndian); + Memory memory(dump, 0x89979731eb060ed4ULL); + memory.Append(1729, 42); + Label l = memory.Here(); + ASSERT_EQ(0x89979731eb060ed4ULL + 1729, l.Value()); +} + +TEST(Context, X86) { + Dump dump(0, kLittleEndian); + assert(x86_raw_context.context_flags & MD_CONTEXT_X86); + Context context(dump, x86_raw_context); + string contents; + ASSERT_TRUE(context.GetContents(&contents)); + EXPECT_EQ(sizeof(x86_expected_contents), contents.size()); + EXPECT_TRUE(memcmp(contents.data(), x86_expected_contents, contents.size()) + == 0); +} + +TEST(ContextDeathTest, X86BadFlags) { + Dump dump(0, kLittleEndian); + MDRawContextX86 raw; + raw.context_flags = 0; + ASSERT_DEATH(Context context(dump, raw);, + "context\\.context_flags & 0x[0-9a-f]+"); +} + +TEST(ContextDeathTest, X86BadEndianness) { + Dump dump(0, kBigEndian); + MDRawContextX86 raw; + raw.context_flags = MD_CONTEXT_X86; + ASSERT_DEATH(Context context(dump, raw);, + "dump\\.endianness\\(\\) == kLittleEndian"); +} + +TEST(Thread, Simple) { + Dump dump(0, kLittleEndian); + Context context(dump, x86_raw_context); + context.Finish(0x8665da0c); + Memory stack(dump, 0xaad55a93cc3c0efcULL); + stack.Append("stack contents"); + stack.Finish(0xe08cdbd1); + Thread thread(dump, 0x3d7ec360, stack, context, + 0x3593f44d, // suspend count + 0xab352b82, // priority class + 0x2753d838, // priority + 0xeb2de4be3f29e3e9ULL); // thread environment block + string contents; + ASSERT_TRUE(thread.GetContents(&contents)); + static const u_int8_t expected_bytes[] = { + 0x60, 0xc3, 0x7e, 0x3d, // thread id + 0x4d, 0xf4, 0x93, 0x35, // suspend count + 0x82, 0x2b, 0x35, 0xab, // priority class + 0x38, 0xd8, 0x53, 0x27, // priority + 0xe9, 0xe3, 0x29, 0x3f, 0xbe, 0xe4, 0x2d, 0xeb, // thread environment block + 0xfc, 0x0e, 0x3c, 0xcc, 0x93, 0x5a, 0xd5, 0xaa, // stack address + 0x0e, 0x00, 0x00, 0x00, // stack size + 0xd1, 0xdb, 0x8c, 0xe0, // stack MDRVA + 0xcc, 0x02, 0x00, 0x00, // context size + 0x0c, 0xda, 0x65, 0x86 // context MDRVA + }; + EXPECT_EQ(sizeof(expected_bytes), contents.size()); + EXPECT_TRUE(memcmp(contents.data(), expected_bytes, contents.size()) == 0); +} + +TEST(String, Simple) { + Dump dump(0, kBigEndian); + String s(dump, "All mimsy were the borogoves"); + string contents; + ASSERT_TRUE(s.GetContents(&contents)); + static const char expected[] = + "\x00\x00\x00\x38\0A\0l\0l\0 \0m\0i\0m\0s\0y\0 \0w\0e\0r\0e" + "\0 \0t\0h\0e\0 \0b\0o\0r\0o\0g\0o\0v\0e\0s"; + string expected_string(expected, sizeof(expected) - 1); + EXPECT_EQ(expected_string, contents); +} + +TEST(String, CiteStringIn) { + Dump dump(0, kLittleEndian); + String s(dump, "and the mome wraths outgrabe"); + Section section(dump); + section.Append("initial"); + s.CiteStringIn(§ion); + s.Finish(0xdc2bb469); + string contents; + ASSERT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("initial\x69\xb4\x2b\xdc", 7 + 4), contents); +} + +TEST(List, Empty) { + Dump dump(0, kBigEndian); + List
list(dump, 0x2442779c); + EXPECT_TRUE(list.Empty()); + list.Finish(0x84e09808); + string contents; + ASSERT_TRUE(list.GetContents(&contents)); + EXPECT_EQ(string("\0\0\0\0", 4), contents); +} + +TEST(List, Two) { + Dump dump(0, kBigEndian); + List
list(dump, 0x26c9f498); + Section section1(dump); + section1.Append("section one contents"); + EXPECT_TRUE(list.Empty()); + list.Add(§ion1); + EXPECT_FALSE(list.Empty()); + Section section2(dump); + section2.Append("section two contents"); + list.Add(§ion2); + list.Finish(0x1e5bb60e); + string contents; + ASSERT_TRUE(list.GetContents(&contents)); + EXPECT_EQ(string("\0\0\0\x02section one contentssection two contents", 44), + contents); +} + +TEST(Dump, Header) { + Dump dump(0x9f738b33685cc84cULL, kLittleEndian, 0xb3817faf, 0x2c741c0a); + dump.Finish(); + string contents; + ASSERT_TRUE(dump.GetContents(&contents)); + ASSERT_EQ(string("\x4d\x44\x4d\x50" // signature + "\xaf\x7f\x81\xb3" // version + "\0\0\0\0" // stream count + "\x20\0\0\0" // directory RVA (could be anything) + "\0\0\0\0" // checksum + "\x0a\x1c\x74\x2c" // time_date_stamp + "\x4c\xc8\x5c\x68\x33\x8b\x73\x9f", // flags + 32), + contents); +} + +TEST(Dump, HeaderBigEndian) { + Dump dump(0x206ce3cc6fb8e0f0ULL, kBigEndian, 0x161693e2, 0x35667744); + dump.Finish(); + string contents; + ASSERT_TRUE(dump.GetContents(&contents)); + ASSERT_EQ(string("\x50\x4d\x44\x4d" // signature + "\x16\x16\x93\xe2" // version + "\0\0\0\0" // stream count + "\0\0\0\x20" // directory RVA (could be anything) + "\0\0\0\0" // checksum + "\x35\x66\x77\x44" // time_date_stamp + "\x20\x6c\xe3\xcc\x6f\xb8\xe0\xf0", // flags + 32), + contents); +} + +TEST(Dump, OneSection) { + Dump dump(0, kLittleEndian); + Section section(dump); + section.Append("section contents"); + dump.Add(§ion); + dump.Finish(); + string dump_contents; + // Just check for undefined labels; don't worry about the contents. + ASSERT_TRUE(dump.GetContents(&dump_contents)); + + Section referencing_section(dump); + section.CiteLocationIn(&referencing_section); + string contents; + ASSERT_TRUE(referencing_section.GetContents(&contents)); + ASSERT_EQ(string("\x10\0\0\0\x20\0\0\0", 8), contents); +} diff --git a/src/processor/synth_minidump_unittest_data.h b/src/processor/synth_minidump_unittest_data.h new file mode 100644 index 00000000..7036d2cb --- /dev/null +++ b/src/processor/synth_minidump_unittest_data.h @@ -0,0 +1,246 @@ +// -*- mode: C++ -*- + +// Not copyrightable: random test data. +// synth_minidump_unittest_data.h: verbose test data for SynthMinidump tests. + +#ifndef PROCESSOR_SYNTH_MINIDUMP_UNITTEST_DATA_H_ +#define PROCESSOR_SYNTH_MINIDUMP_UNITTEST_DATA_H_ + +#include "google_breakpad/common/minidump_format.h" + +static const MDRawContextX86 x86_raw_context = { + 0xded5d71b, // context_flags + 0x9fdb432e, // dr0 + 0x26b7a81a, // dr1 + 0xcac7e348, // dr2 + 0xcf99ec09, // dr3 + 0x7dc8c2cd, // dr6 + 0x21deb880, // dr7 + + // float_save + { + 0x8a5d2bb0, // control_word + 0x0286c4c9, // status_word + 0xf1feea21, // tag_word + 0xb2d40576, // error_offset + 0x48146cde, // error_selector + 0x983f9b21, // data_offset + 0x475be12c, // data_selector + + // register_area + { + 0xd9, 0x04, 0x20, 0x6b, 0x88, 0x3a, 0x3f, 0xd5, + 0x59, 0x7a, 0xa9, 0xeb, 0xd0, 0x5c, 0xdf, 0xfe, + 0xad, 0xdd, 0x4a, 0x8b, 0x10, 0xcc, 0x9a, 0x33, + 0xcb, 0xb6, 0xf7, 0x86, 0xcd, 0x69, 0x25, 0xae, + 0x25, 0xe5, 0x7a, 0xa1, 0x8f, 0xb2, 0x84, 0xd9, + 0xf7, 0x2d, 0x8a, 0xa1, 0x80, 0x81, 0x7f, 0x67, + 0x07, 0xa8, 0x23, 0xf1, 0x8c, 0xdc, 0xd8, 0x04, + 0x8b, 0x9d, 0xb1, 0xcd, 0x61, 0x0c, 0x9c, 0x69, + 0xc7, 0x8d, 0x17, 0xb6, 0xe5, 0x0b, 0x94, 0xf7, + 0x78, 0x9b, 0x63, 0x49, 0xba, 0xfc, 0x08, 0x4d + }, + + 0x84c53a90, // cr0_npx_state + }, + + 0x79f71e76, // gs + 0x8107bd25, // fs + 0x452d2921, // es + 0x87ec2875, // ds + 0xf8bb73f5, // edi + 0xa63ebb88, // esi + 0x95d35ebe, // ebx + 0x17aa2456, // edx + 0x135fa208, // ecx + 0x500615e6, // eax + 0x66d14205, // ebp + 0x000719a5, // eip + 0x477b481b, // cs + 0x8684dfba, // eflags + 0xe33ccddf, // esp + 0xc0e65d33, // ss + + // extended_registers + { + 0x68, 0x63, 0xdf, 0x50, 0xf7, 0x3b, 0xe8, 0xe5, + 0xcb, 0xd6, 0x66, 0x60, 0xe5, 0xa3, 0x58, 0xb3, + 0x6f, 0x34, 0xca, 0x02, 0x9b, 0x5f, 0xd0, 0x41, + 0xbd, 0xc5, 0x2d, 0xf8, 0xff, 0x15, 0xa2, 0xd0, + 0xe3, 0x2b, 0x3b, 0x8a, 0x9f, 0xc3, 0x9e, 0x28, + 0x0a, 0xc2, 0xac, 0x3b, 0x67, 0x37, 0x01, 0xfd, + 0xc3, 0xaf, 0x60, 0xf6, 0x2c, 0x4f, 0xa9, 0x52, + 0x92, 0xe5, 0x28, 0xde, 0x34, 0xb6, 0x2e, 0x44, + 0x15, 0xa4, 0xb6, 0xe4, 0xc9, 0x1a, 0x14, 0xb9, + 0x51, 0x33, 0x3c, 0xe0, 0xc7, 0x94, 0xf0, 0xf7, + 0x78, 0xdd, 0xe5, 0xca, 0xb7, 0xa6, 0xe0, 0x14, + 0xa6, 0x03, 0xab, 0x77, 0xad, 0xbd, 0xd2, 0x53, + 0x3d, 0x07, 0xe7, 0xaf, 0x90, 0x44, 0x71, 0xbe, + 0x0c, 0xdf, 0x2b, 0x97, 0x40, 0x48, 0xd5, 0xf9, + 0x62, 0x03, 0x91, 0x84, 0xd6, 0xdd, 0x29, 0x97, + 0x35, 0x02, 0xfb, 0x59, 0x97, 0xb0, 0xec, 0xa9, + 0x39, 0x6f, 0x81, 0x71, 0x2a, 0xf0, 0xe7, 0x2c, + 0x4e, 0x93, 0x90, 0xcb, 0x67, 0x69, 0xde, 0xd7, + 0x68, 0x3b, 0x0f, 0x69, 0xa8, 0xf4, 0xa8, 0x83, + 0x42, 0x80, 0x47, 0x65, 0x7a, 0xc9, 0x19, 0x5d, + 0xcb, 0x43, 0xa5, 0xff, 0xf8, 0x9e, 0x62, 0xf4, + 0xe2, 0x6c, 0xcc, 0x17, 0x55, 0x7c, 0x0d, 0x5c, + 0x8d, 0x16, 0x01, 0xd7, 0x3a, 0x0c, 0xf4, 0x7f, + 0x71, 0xdc, 0x48, 0xe9, 0x4b, 0xfe, 0x1a, 0xd0, + 0x04, 0x15, 0x33, 0xec, 0x78, 0xc6, 0x7e, 0xde, + 0x7c, 0x23, 0x18, 0x8d, 0x8f, 0xc2, 0x74, 0xc1, + 0x48, 0xcd, 0x5d, 0xee, 0xee, 0x81, 0x9e, 0x49, + 0x47, 0x8a, 0xf8, 0x61, 0xa3, 0x9c, 0x81, 0x96, + 0xbe, 0x2b, 0x5e, 0xbc, 0xcd, 0x34, 0x0a, 0x2a, + 0x3b, 0x8b, 0x7d, 0xa1, 0xf2, 0x8d, 0xb4, 0x51, + 0x9e, 0x14, 0x78, 0xa3, 0x58, 0x65, 0x2d, 0xd6, + 0x50, 0x40, 0x36, 0x32, 0x31, 0xd4, 0x3e, 0xc2, + 0xe0, 0x87, 0x1c, 0x05, 0x95, 0x80, 0x84, 0x24, + 0x08, 0x6f, 0x5b, 0xc7, 0xe1, 0x1d, 0xd5, 0xa3, + 0x94, 0x44, 0xa1, 0x7c, 0xd8, 0x4b, 0x86, 0xd2, + 0xc6, 0xa9, 0xf3, 0xe2, 0x4d, 0x6e, 0x1f, 0x0e, + 0xf2, 0xf5, 0x71, 0xf9, 0x71, 0x05, 0x24, 0xc9, + 0xc1, 0xe8, 0x91, 0x42, 0x61, 0x86, 0x57, 0x68, + 0xd9, 0xc9, 0x1d, 0xd5, 0x5a, 0xe9, 0xba, 0xe6, + 0x15, 0x8f, 0x87, 0xbd, 0x62, 0x56, 0xed, 0xda, + 0xc2, 0xa5, 0xd5, 0x39, 0xac, 0x05, 0x10, 0x14, + 0x4a, 0xe7, 0xe7, 0x3c, 0x3f, 0xb7, 0xbb, 0xed, + 0x01, 0x6e, 0xcd, 0xee, 0x81, 0xb4, 0x62, 0xf4, + 0x62, 0x16, 0xff, 0x20, 0xb4, 0xf0, 0xbc, 0xff, + 0x7d, 0xd9, 0xcf, 0x95, 0x30, 0x27, 0xe0, 0x2f, + 0x98, 0x53, 0x80, 0x15, 0x13, 0xef, 0x44, 0x58, + 0x12, 0x16, 0xdb, 0x11, 0xef, 0x73, 0x51, 0xcd, + 0x42, 0x3f, 0x98, 0x6c, 0xc9, 0x68, 0xc3, 0xf4, + 0x5b, 0x0f, 0x5d, 0x77, 0xed, 0xdf, 0x0f, 0xff, + 0xb8, 0x69, 0x98, 0x50, 0x77, 0x7a, 0xe8, 0x90, + 0x27, 0x46, 0x10, 0xd2, 0xb5, 0x00, 0x3b, 0x36, + 0x43, 0x6d, 0x67, 0x41, 0x20, 0x3a, 0x32, 0xe0, + 0x2e, 0x5a, 0xfb, 0x4e, 0x4f, 0xa4, 0xf7, 0xc2, + 0xe6, 0x81, 0x1a, 0x51, 0xa8, 0x7c, 0xd4, 0x60, + 0x7c, 0x45, 0xe2, 0xba, 0x5b, 0x42, 0xf3, 0xbf, + 0x28, 0xaa, 0xf2, 0x90, 0xe4, 0x94, 0xdd, 0xaa, + 0x22, 0xd3, 0x71, 0x33, 0xa1, 0x01, 0x43, 0x0e, + 0xfa, 0x46, 0xd2, 0x6e, 0x55, 0x5e, 0x49, 0xeb, + 0x94, 0xf0, 0xb0, 0xb1, 0x2e, 0xf2, 0x3d, 0x6c, + 0x00, 0x5e, 0x01, 0x56, 0x3b, 0xfd, 0x5b, 0xa1, + 0x2f, 0x63, 0x1d, 0xbf, 0xf9, 0xd8, 0x13, 0xf7, + 0x4d, 0xb7, 0x1e, 0x3d, 0x98, 0xd2, 0xee, 0xb8, + 0x48, 0xc8, 0x5b, 0x91, 0x0f, 0x54, 0x9e, 0x26, + 0xb2, 0xc7, 0x3a, 0x6c, 0x8a, 0x35, 0xe1, 0xba + } +}; + +static const u_int8_t x86_expected_contents[] = { + 0x1b, 0xd7, 0xd5, 0xde, + 0x2e, 0x43, 0xdb, 0x9f, + 0x1a, 0xa8, 0xb7, 0x26, + 0x48, 0xe3, 0xc7, 0xca, + 0x09, 0xec, 0x99, 0xcf, + 0xcd, 0xc2, 0xc8, 0x7d, + 0x80, 0xb8, 0xde, 0x21, + 0xb0, 0x2b, 0x5d, 0x8a, + 0xc9, 0xc4, 0x86, 0x02, + 0x21, 0xea, 0xfe, 0xf1, + 0x76, 0x05, 0xd4, 0xb2, + 0xde, 0x6c, 0x14, 0x48, + 0x21, 0x9b, 0x3f, 0x98, + 0x2c, 0xe1, 0x5b, 0x47, + + // float_save.register_area --- unswapped + 0xd9, 0x04, 0x20, 0x6b, 0x88, 0x3a, 0x3f, 0xd5, + 0x59, 0x7a, 0xa9, 0xeb, 0xd0, 0x5c, 0xdf, 0xfe, + 0xad, 0xdd, 0x4a, 0x8b, 0x10, 0xcc, 0x9a, 0x33, + 0xcb, 0xb6, 0xf7, 0x86, 0xcd, 0x69, 0x25, 0xae, + 0x25, 0xe5, 0x7a, 0xa1, 0x8f, 0xb2, 0x84, 0xd9, + 0xf7, 0x2d, 0x8a, 0xa1, 0x80, 0x81, 0x7f, 0x67, + 0x07, 0xa8, 0x23, 0xf1, 0x8c, 0xdc, 0xd8, 0x04, + 0x8b, 0x9d, 0xb1, 0xcd, 0x61, 0x0c, 0x9c, 0x69, + 0xc7, 0x8d, 0x17, 0xb6, 0xe5, 0x0b, 0x94, 0xf7, + 0x78, 0x9b, 0x63, 0x49, 0xba, 0xfc, 0x08, 0x4d, + + 0x90, 0x3a, 0xc5, 0x84, + 0x76, 0x1e, 0xf7, 0x79, + 0x25, 0xbd, 0x07, 0x81, + 0x21, 0x29, 0x2d, 0x45, + 0x75, 0x28, 0xec, 0x87, + 0xf5, 0x73, 0xbb, 0xf8, + 0x88, 0xbb, 0x3e, 0xa6, + 0xbe, 0x5e, 0xd3, 0x95, + 0x56, 0x24, 0xaa, 0x17, + 0x08, 0xa2, 0x5f, 0x13, + 0xe6, 0x15, 0x06, 0x50, + 0x05, 0x42, 0xd1, 0x66, + 0xa5, 0x19, 0x07, 0x00, + 0x1b, 0x48, 0x7b, 0x47, + 0xba, 0xdf, 0x84, 0x86, + 0xdf, 0xcd, 0x3c, 0xe3, + 0x33, 0x5d, 0xe6, 0xc0, + + // extended_registers --- unswapped + 0x68, 0x63, 0xdf, 0x50, 0xf7, 0x3b, 0xe8, 0xe5, + 0xcb, 0xd6, 0x66, 0x60, 0xe5, 0xa3, 0x58, 0xb3, + 0x6f, 0x34, 0xca, 0x02, 0x9b, 0x5f, 0xd0, 0x41, + 0xbd, 0xc5, 0x2d, 0xf8, 0xff, 0x15, 0xa2, 0xd0, + 0xe3, 0x2b, 0x3b, 0x8a, 0x9f, 0xc3, 0x9e, 0x28, + 0x0a, 0xc2, 0xac, 0x3b, 0x67, 0x37, 0x01, 0xfd, + 0xc3, 0xaf, 0x60, 0xf6, 0x2c, 0x4f, 0xa9, 0x52, + 0x92, 0xe5, 0x28, 0xde, 0x34, 0xb6, 0x2e, 0x44, + 0x15, 0xa4, 0xb6, 0xe4, 0xc9, 0x1a, 0x14, 0xb9, + 0x51, 0x33, 0x3c, 0xe0, 0xc7, 0x94, 0xf0, 0xf7, + 0x78, 0xdd, 0xe5, 0xca, 0xb7, 0xa6, 0xe0, 0x14, + 0xa6, 0x03, 0xab, 0x77, 0xad, 0xbd, 0xd2, 0x53, + 0x3d, 0x07, 0xe7, 0xaf, 0x90, 0x44, 0x71, 0xbe, + 0x0c, 0xdf, 0x2b, 0x97, 0x40, 0x48, 0xd5, 0xf9, + 0x62, 0x03, 0x91, 0x84, 0xd6, 0xdd, 0x29, 0x97, + 0x35, 0x02, 0xfb, 0x59, 0x97, 0xb0, 0xec, 0xa9, + 0x39, 0x6f, 0x81, 0x71, 0x2a, 0xf0, 0xe7, 0x2c, + 0x4e, 0x93, 0x90, 0xcb, 0x67, 0x69, 0xde, 0xd7, + 0x68, 0x3b, 0x0f, 0x69, 0xa8, 0xf4, 0xa8, 0x83, + 0x42, 0x80, 0x47, 0x65, 0x7a, 0xc9, 0x19, 0x5d, + 0xcb, 0x43, 0xa5, 0xff, 0xf8, 0x9e, 0x62, 0xf4, + 0xe2, 0x6c, 0xcc, 0x17, 0x55, 0x7c, 0x0d, 0x5c, + 0x8d, 0x16, 0x01, 0xd7, 0x3a, 0x0c, 0xf4, 0x7f, + 0x71, 0xdc, 0x48, 0xe9, 0x4b, 0xfe, 0x1a, 0xd0, + 0x04, 0x15, 0x33, 0xec, 0x78, 0xc6, 0x7e, 0xde, + 0x7c, 0x23, 0x18, 0x8d, 0x8f, 0xc2, 0x74, 0xc1, + 0x48, 0xcd, 0x5d, 0xee, 0xee, 0x81, 0x9e, 0x49, + 0x47, 0x8a, 0xf8, 0x61, 0xa3, 0x9c, 0x81, 0x96, + 0xbe, 0x2b, 0x5e, 0xbc, 0xcd, 0x34, 0x0a, 0x2a, + 0x3b, 0x8b, 0x7d, 0xa1, 0xf2, 0x8d, 0xb4, 0x51, + 0x9e, 0x14, 0x78, 0xa3, 0x58, 0x65, 0x2d, 0xd6, + 0x50, 0x40, 0x36, 0x32, 0x31, 0xd4, 0x3e, 0xc2, + 0xe0, 0x87, 0x1c, 0x05, 0x95, 0x80, 0x84, 0x24, + 0x08, 0x6f, 0x5b, 0xc7, 0xe1, 0x1d, 0xd5, 0xa3, + 0x94, 0x44, 0xa1, 0x7c, 0xd8, 0x4b, 0x86, 0xd2, + 0xc6, 0xa9, 0xf3, 0xe2, 0x4d, 0x6e, 0x1f, 0x0e, + 0xf2, 0xf5, 0x71, 0xf9, 0x71, 0x05, 0x24, 0xc9, + 0xc1, 0xe8, 0x91, 0x42, 0x61, 0x86, 0x57, 0x68, + 0xd9, 0xc9, 0x1d, 0xd5, 0x5a, 0xe9, 0xba, 0xe6, + 0x15, 0x8f, 0x87, 0xbd, 0x62, 0x56, 0xed, 0xda, + 0xc2, 0xa5, 0xd5, 0x39, 0xac, 0x05, 0x10, 0x14, + 0x4a, 0xe7, 0xe7, 0x3c, 0x3f, 0xb7, 0xbb, 0xed, + 0x01, 0x6e, 0xcd, 0xee, 0x81, 0xb4, 0x62, 0xf4, + 0x62, 0x16, 0xff, 0x20, 0xb4, 0xf0, 0xbc, 0xff, + 0x7d, 0xd9, 0xcf, 0x95, 0x30, 0x27, 0xe0, 0x2f, + 0x98, 0x53, 0x80, 0x15, 0x13, 0xef, 0x44, 0x58, + 0x12, 0x16, 0xdb, 0x11, 0xef, 0x73, 0x51, 0xcd, + 0x42, 0x3f, 0x98, 0x6c, 0xc9, 0x68, 0xc3, 0xf4, + 0x5b, 0x0f, 0x5d, 0x77, 0xed, 0xdf, 0x0f, 0xff, + 0xb8, 0x69, 0x98, 0x50, 0x77, 0x7a, 0xe8, 0x90, + 0x27, 0x46, 0x10, 0xd2, 0xb5, 0x00, 0x3b, 0x36, + 0x43, 0x6d, 0x67, 0x41, 0x20, 0x3a, 0x32, 0xe0, + 0x2e, 0x5a, 0xfb, 0x4e, 0x4f, 0xa4, 0xf7, 0xc2, + 0xe6, 0x81, 0x1a, 0x51, 0xa8, 0x7c, 0xd4, 0x60, + 0x7c, 0x45, 0xe2, 0xba, 0x5b, 0x42, 0xf3, 0xbf, + 0x28, 0xaa, 0xf2, 0x90, 0xe4, 0x94, 0xdd, 0xaa, + 0x22, 0xd3, 0x71, 0x33, 0xa1, 0x01, 0x43, 0x0e, + 0xfa, 0x46, 0xd2, 0x6e, 0x55, 0x5e, 0x49, 0xeb, + 0x94, 0xf0, 0xb0, 0xb1, 0x2e, 0xf2, 0x3d, 0x6c, + 0x00, 0x5e, 0x01, 0x56, 0x3b, 0xfd, 0x5b, 0xa1, + 0x2f, 0x63, 0x1d, 0xbf, 0xf9, 0xd8, 0x13, 0xf7, + 0x4d, 0xb7, 0x1e, 0x3d, 0x98, 0xd2, 0xee, 0xb8, + 0x48, 0xc8, 0x5b, 0x91, 0x0f, 0x54, 0x9e, 0x26, + 0xb2, 0xc7, 0x3a, 0x6c, 0x8a, 0x35, 0xe1, 0xba +}; + +#endif // PROCESSOR_SYNTH_MINIDUMP_UNITTEST_DATA_H_ diff --git a/src/processor/test_assembler.cc b/src/processor/test_assembler.cc new file mode 100644 index 00000000..5a36166a --- /dev/null +++ b/src/processor/test_assembler.cc @@ -0,0 +1,357 @@ +// Copyright (c) 2010, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Original author: Jim Blandy + +// test_assembler.cc: Implementation of google_breakpad::TestAssembler. +// See test_assembler.h for details. + +#include +#include +#include + +#include "processor/test_assembler.h" + +namespace google_breakpad { +namespace TestAssembler { + +using std::back_insert_iterator; + +Label::Label() : value_(new Binding()) { } +Label::Label(u_int64_t value) : value_(new Binding(value)) { } +Label::Label(const Label &label) { + value_ = label.value_; + value_->Acquire(); +} +Label::~Label() { + if (value_->Release()) delete value_; +} + +Label &Label::operator=(u_int64_t value) { + value_->Set(NULL, value); + return *this; +} + +Label &Label::operator=(const Label &label) { + value_->Set(label.value_, 0); + return *this; +} + +Label Label::operator+(u_int64_t addend) const { + Label l; + l.value_->Set(this->value_, addend); + return l; +} + +Label Label::operator-(u_int64_t subtrahend) const { + Label l; + l.value_->Set(this->value_, -subtrahend); + return l; +} + +// When NDEBUG is #defined, assert doesn't evaluate its argument. This +// means you can't simply use assert to check the return value of a +// function with necessary side effects. +// +// ALWAYS_EVALUATE_AND_ASSERT(x) evaluates x regardless of whether +// NDEBUG is #defined; when NDEBUG is not #defined, it further asserts +// that x is true. +#ifdef NDEBUG +#define ALWAYS_EVALUATE_AND_ASSERT(x) x +#else +#define ALWAYS_EVALUATE_AND_ASSERT(x) assert(x) +#endif + +u_int64_t Label::operator-(const Label &label) const { + u_int64_t offset; + ALWAYS_EVALUATE_AND_ASSERT(IsKnownOffsetFrom(label, &offset)); + return offset; +} + +u_int64_t Label::Value() const { + u_int64_t v; + ALWAYS_EVALUATE_AND_ASSERT(IsKnownConstant(&v)); + return v; +}; + +bool Label::IsKnownConstant(u_int64_t *value_p) const { + Binding *base; + u_int64_t addend; + value_->Get(&base, &addend); + if (base != NULL) return false; + if (value_p) *value_p = addend; + return true; +} + +bool Label::IsKnownOffsetFrom(const Label &label, u_int64_t *offset_p) const +{ + Binding *label_base, *this_base; + u_int64_t label_addend, this_addend; + label.value_->Get(&label_base, &label_addend); + value_->Get(&this_base, &this_addend); + // If this and label are related, Get will find their final + // common ancestor, regardless of how indirect the relation is. This + // comparison also handles the constant vs. constant case. + if (this_base != label_base) return false; + if (offset_p) *offset_p = this_addend - label_addend; + return true; +} + +Label::Binding::Binding() : base_(this), addend_(), reference_count_(1) { } + +Label::Binding::Binding(u_int64_t addend) + : base_(NULL), addend_(addend), reference_count_(1) { } + +Label::Binding::~Binding() { + assert(reference_count_ == 0); + if (base_ && base_ != this && base_->Release()) + delete base_; +} + +void Label::Binding::Set(Binding *binding, u_int64_t addend) { + if (!base_ && !binding) { + // We're equating two constants. This could be okay. + assert(addend_ == addend); + } else if (!base_) { + // We are a known constant, but BINDING may not be, so turn the + // tables and try to set BINDING's value instead. + binding->Set(NULL, addend_ - addend); + } else { + if (binding) { + // Find binding's final value. Since the final value is always either + // completely unconstrained or a constant, never a reference to + // another variable (otherwise, it wouldn't be final), this + // guarantees we won't create cycles here, even for code like this: + // l = m, m = n, n = l; + u_int64_t binding_addend; + binding->Get(&binding, &binding_addend); + addend += binding_addend; + } + + // It seems likely that setting a binding to itself is a bug + // (although I can imagine this might turn out to be helpful to + // permit). + assert(binding != this); + + if (base_ != this) { + // Set the other bindings on our chain as well. Note that this + // is sufficient even though binding relationships form trees: + // All binding operations traverse their chains to the end, and + // all bindings related to us share some tail of our chain, so + // they will see the changes we make here. + base_->Set(binding, addend - addend_); + // We're not going to use base_ any more. + if (base_->Release()) delete base_; + } + + // Adopt BINDING as our base. Note that it should be correct to + // acquire here, after the release above, even though the usual + // reference-counting rules call for acquiring first, and then + // releasing: the self-reference assertion above should have + // complained if BINDING were 'this' or anywhere along our chain, + // so we didn't release BINDING. + if (binding) binding->Acquire(); + base_ = binding; + addend_ = addend; + } +} + +void Label::Binding::Get(Binding **base, u_int64_t *addend) { + if (base_ && base_ != this) { + // Recurse to find the end of our reference chain (the root of our + // tree), and then rewrite every binding along the chain to refer + // to it directly, adjusting addends appropriately. (This is why + // this member function isn't this-const.) + Binding *final_base; + u_int64_t final_addend; + base_->Get(&final_base, &final_addend); + if (final_base) final_base->Acquire(); + if (base_->Release()) delete base_; + base_ = final_base; + addend_ += final_addend; + } + *base = base_; + *addend = addend_; +} + +template +static inline void InsertEndian(TestAssembler::Endianness endianness, + size_t size, u_int64_t number, Inserter dest) { + if (endianness == kLittleEndian) { + for (size_t i = 0; i < size; i++) { + *dest++ = (char) (number & 0xff); + number >>= 8; + } + } else { + assert(endianness == kBigEndian); + // The loop condition is odd, but it's correct for size_t. + for (size_t i = size - 1; i < size; i--) + *dest++ = (char) ((number >> (i * 8)) & 0xff); + } +} + +Section &Section::Append(Endianness endianness, size_t size, u_int64_t number) { + InsertEndian(endianness, size, number, + back_insert_iterator(contents_)); + return *this; +} + +Section &Section::Append(Endianness endianness, size_t size, + const Label &label) { + // If this label's value is known, there's no reason to waste an + // entry in references_ on it. + u_int64_t value; + if (label.IsKnownConstant(&value)) + return Append(endianness, size, value); + + // This will get caught when the references are resolved, but it's + // nicer to find out earlier. + assert(endianness != kUnsetEndian); + + references_.push_back(Reference(contents_.size(), endianness, size, label)); + contents_.append(size, 0); + return *this; +} + +#define ENDIANNESS_L kLittleEndian +#define ENDIANNESS_B kBigEndian +#define ENDIANNESS(e) ENDIANNESS_ ## e + +#define DEFINE_SHORT_APPEND_NUMBER_ENDIAN(e, bits) \ + Section &Section::e ## bits(u_int ## bits ## _t v) { \ + InsertEndian(ENDIANNESS(e), bits / 8, v, \ + back_insert_iterator(contents_)); \ + return *this; \ + } + +#define DEFINE_SHORT_APPEND_LABEL_ENDIAN(e, bits) \ + Section &Section::e ## bits(const Label &v) { \ + return Append(ENDIANNESS(e), bits / 8, v); \ + } + +// Define L16, B32, and friends. +#define DEFINE_SHORT_APPEND_ENDIAN(e, bits) \ + DEFINE_SHORT_APPEND_NUMBER_ENDIAN(e, bits) \ + DEFINE_SHORT_APPEND_LABEL_ENDIAN(e, bits) + +DEFINE_SHORT_APPEND_LABEL_ENDIAN(L, 8); +DEFINE_SHORT_APPEND_LABEL_ENDIAN(B, 8); +DEFINE_SHORT_APPEND_ENDIAN(L, 16); +DEFINE_SHORT_APPEND_ENDIAN(L, 32); +DEFINE_SHORT_APPEND_ENDIAN(L, 64); +DEFINE_SHORT_APPEND_ENDIAN(B, 16); +DEFINE_SHORT_APPEND_ENDIAN(B, 32); +DEFINE_SHORT_APPEND_ENDIAN(B, 64); + +#define DEFINE_SHORT_APPEND_NUMBER_DEFAULT(bits) \ + Section &Section::D ## bits(u_int ## bits ## _t v) { \ + InsertEndian(endianness_, bits / 8, v, \ + back_insert_iterator(contents_)); \ + return *this; \ + } +#define DEFINE_SHORT_APPEND_LABEL_DEFAULT(bits) \ + Section &Section::D ## bits(const Label &v) { \ + return Append(endianness_, bits / 8, v); \ + } +#define DEFINE_SHORT_APPEND_DEFAULT(bits) \ + DEFINE_SHORT_APPEND_NUMBER_DEFAULT(bits) \ + DEFINE_SHORT_APPEND_LABEL_DEFAULT(bits) + +DEFINE_SHORT_APPEND_LABEL_DEFAULT(8) +DEFINE_SHORT_APPEND_DEFAULT(16); +DEFINE_SHORT_APPEND_DEFAULT(32); +DEFINE_SHORT_APPEND_DEFAULT(64); + +Section &Section::Append(const Section §ion) { + size_t base = contents_.size(); + contents_.append(section.contents_); + for (vector::const_iterator it = section.references_.begin(); + it != section.references_.end(); it++) + references_.push_back(Reference(base + it->offset, it->endianness, + it->size, it->label)); + return *this; +} + +Section &Section::LEB128(long long value) { + while (value < -0x40 || 0x3f < value) { + contents_ += (value & 0x7f) | 0x80; + if (value < 0) + value = (value >> 7) | ~(((unsigned long long) -1) >> 7); + else + value = (value >> 7); + } + contents_ += value & 0x7f; + return *this; +} + +Section &Section::ULEB128(u_int64_t value) { + while (value > 0x7f) { + contents_ += (value & 0x7f) | 0x80; + value = (value >> 7); + } + contents_ += value; + return *this; +} + +Section &Section::Align(size_t alignment, u_int8_t pad_byte) { + // ALIGNMENT must be a power of two. + assert(((alignment - 1) & alignment) == 0); + size_t new_size = (contents_.size() + alignment - 1) & ~(alignment - 1); + contents_.append(new_size - contents_.size(), pad_byte); + assert((contents_.size() & (alignment - 1)) == 0); + return *this; +} + +void Section::Clear() { + contents_.clear(); + references_.clear(); +} + +bool Section::GetContents(string *contents) { + // For each label reference, find the label's value, and patch it into + // the section's contents. + for (size_t i = 0; i < references_.size(); i++) { + Reference &r = references_[i]; + u_int64_t value; + if (!r.label.IsKnownConstant(&value)) { + fprintf(stderr, "Undefined label #%d at offset 0x%x\n", i, r.offset); + return false; + } + assert(r.offset < contents_.size()); + assert(contents_.size() - r.offset >= r.size); + InsertEndian(r.endianness, r.size, value, contents_.begin() + r.offset); + } + contents->clear(); + std::swap(contents_, *contents); + references_.clear(); + return true; +} + +} // namespace TestAssembler +} // namespace google_breakpad diff --git a/src/processor/test_assembler.h b/src/processor/test_assembler.h new file mode 100644 index 00000000..560f7aef --- /dev/null +++ b/src/processor/test_assembler.h @@ -0,0 +1,472 @@ +// -*- mode: C++ -*- + +// Copyright (c) 2010, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Original author: Jim Blandy + +// test-assembler.h: interface to class for building complex binary streams. + +// To test the Breakpad symbol dumper and processor thoroughly, for +// all combinations of host system and minidump processor +// architecture, we need to be able to easily generate complex test +// data like debugging information and minidump files. +// +// For example, if we want our unit tests to provide full code +// coverage for stack walking, it may be difficult to persuade the +// compiler to generate every possible sort of stack walking +// information that we want to support; there are probably DWARF CFI +// opcodes that GCC never emits. Similarly, if we want to test our +// error handling, we will need to generate damaged minidumps or +// debugging information that (we hope) the client or compiler will +// never produce on its own. +// +// google_breakpad::TestAssembler provides a predictable and +// (relatively) simple way to generate complex formatted data streams +// like minidumps and CFI. Furthermore, because TestAssembler is +// portable, developers without access to (say) Visual Studio or a +// SPARC assembler can still work on test data for those targets. + +#ifndef PROCESSOR_TEST_ASSEMBLER_H_ +#define PROCESSOR_TEST_ASSEMBLER_H_ + +#include +#include +#include + +#include "google_breakpad/common/breakpad_types.h" + +namespace google_breakpad { + +using std::list; +using std::string; +using std::vector; + +namespace TestAssembler { + +// A Label represents a value not yet known that we need to store in a +// section. As long as all the labels a section refers to are defined +// by the time we retrieve its contents as bytes, we can use undefined +// labels freely in that section's construction. +// +// A label can be in one of three states: +// - undefined, +// - defined as the sum of some other label and a constant, or +// - a constant. +// +// A label's value never changes, but it can accumulate constraints. +// Adding labels and integers is permitted, and yields a label. +// Subtracting a constant from a label is permitted, and also yields a +// label. Subtracting two labels that have some relationship to each +// other is permitted, and yields a constant. +// +// For example: +// +// Label a; // a's value is undefined +// Label b; // b's value is undefined +// { +// Label c = a + 4; // okay, even though a's value is unknown +// b = c + 4; // also okay; b is now a+8 +// } +// Label d = b - 2; // okay; d == a+6, even though c is gone +// d.Value(); // error: d's value is not yet known +// d - a; // is 6, even though their values are not known +// a = 12; // now b == 20, and d == 18 +// d.Value(); // 18: no longer an error +// b.Value(); // 20 +// d = 10; // error: d is already defined. +// +// Label objects' lifetimes are unconstrained: notice that, in the +// above example, even though a and b are only related through c, and +// c goes out of scope, the assignment to a sets b's value as well. In +// particular, it's not necessary to ensure that a Label lives beyond +// Sections that refer to it. +class Label { + public: + Label(); // An undefined label. + Label(u_int64_t value); // A label with a fixed value + Label(const Label &value); // A label equal to another. + ~Label(); + + // Return this label's value; it must be known. + // + // Providing this as a cast operator is nifty, but the conversions + // happen in unexpected places. In particular, ISO C++ says that + // Label + size_t becomes ambigious, because it can't decide whether + // to convert the Label to a u_int64_t and then to a size_t, or use + // the overloaded operator that returns a new label, even though the + // former could fail if the label is not yet defined and the latter won't. + u_int64_t Value() const; + + Label &operator=(u_int64_t value); + Label &operator=(const Label &value); + Label operator+(u_int64_t addend) const; + Label operator-(u_int64_t subtrahend) const; + u_int64_t operator-(const Label &subtrahend) const; + + // We could also provide == and != that work on undefined, but + // related, labels. + + // Return true if this label's value is known. If VALUE_P is given, + // set *VALUE_P to the known value if returning true. + bool IsKnownConstant(u_int64_t *value_p = NULL) const; + + // Return true if the offset from LABEL to this label is known. If + // OFFSET_P is given, set *OFFSET_P to the offset when returning true. + // + // You can think of l.KnownOffsetFrom(m, &d) as being like 'd = l-m', + // except that it also returns a value indicating whether the + // subtraction is possible given what we currently know of l and m. + // It can be possible even if we don't know l and m's values. For + // example: + // + // Label l, m; + // m = l + 10; + // l.IsKnownConstant(); // false + // m.IsKnownConstant(); // false + // u_int64_t d; + // l.IsKnownOffsetFrom(m, &d); // true, and sets d to -10. + // l-m // -10 + // m-l // 10 + // m.Value() // error: m's value is not known + bool IsKnownOffsetFrom(const Label &label, u_int64_t *offset_p = NULL) const; + + private: + // A label's value, or if that is not yet known, how the value is + // related to other labels' values. A binding may be: + // - a known constant, + // - constrained to be equal to some other binding plus a constant, or + // - unconstrained, and free to take on any value. + // + // Many labels may point to a single binding, and each binding may + // refer to another, so bindings and labels form trees whose leaves + // are labels, whose interior nodes (and roots) are bindings, and + // where links point from children to parents. Bindings are + // reference counted, allowing labels to be lightweight, copyable, + // assignable, placed in containers, and so on. + class Binding { + public: + Binding(); + Binding(u_int64_t addend); + ~Binding(); + + // Increment our reference count. + void Acquire() { reference_count_++; }; + // Decrement our reference count, and return true if it is zero. + bool Release() { return --reference_count_ == 0; } + + // Set this binding to be equal to BINDING + ADDEND. If BINDING is + // NULL, then set this binding to the known constant ADDEND. + // Update every binding on this binding's chain to point directly + // to BINDING, or to be a constant, with addends adjusted + // appropriately. + void Set(Binding *binding, u_int64_t value); + + // Return what we know about the value of this binding. + // - If this binding's value is a known constant, set BASE to + // NULL, and set ADDEND to its value. + // - If this binding is not a known constant but related to other + // bindings, set BASE to the binding at the end of the relation + // chain (which will always be unconstrained), and set ADDEND to the + // value to add to that binding's value to get this binding's + // value. + // - If this binding is unconstrained, set BASE to this, and leave + // ADDEND unchanged. + void Get(Binding **base, u_int64_t *addend); + + private: + // There are three cases: + // + // - A binding representing a known constant value has base_ NULL, + // and addend_ equal to the value. + // + // - A binding representing a completely unconstrained value has + // base_ pointing to this; addend_ is unused. + // + // - A binding whose value is related to some other binding's + // value has base_ pointing to that other binding, and addend_ + // set to the amount to add to that binding's value to get this + // binding's value. We only represent relationships of the form + // x = y+c. + // + // Thus, the bind_ links form a chain terminating in either a + // known constant value or a completely unconstrained value. Most + // operations on bindings do path compression: they change every + // binding on the chain to point directly to the final value, + // adjusting addends as appropriate. + Binding *base_; + u_int64_t addend_; + + // The number of Labels and Bindings pointing to this binding. + // (When a binding points to itself, indicating a completely + // unconstrained binding, that doesn't count as a reference.) + int reference_count_; + }; + + // This label's value. + Binding *value_; +}; + +inline Label operator+(u_int64_t a, const Label &l) { return l + a; } +// Note that int-Label isn't defined, as negating a Label is not an +// operation we support. + +// Conventions for representing larger numbers as sequences of bytes. +enum Endianness { + kBigEndian, // Big-endian: the most significant byte comes first. + kLittleEndian, // Little-endian: the least significant byte comes first. + kUnsetEndian, // used internally +}; + +// A section is a sequence of bytes, constructed by appending bytes +// to the end. Sections have a convenient and flexible set of member +// functions for appending data in various formats: big-endian and +// little-endian signed and unsigned values of different sizes; +// LEB128 and ULEB128 values (see below), and raw blocks of bytes. +// +// If you need to append a value to a section that is not convenient +// to compute immediately, you can create a label, append the +// label's value to the section, and then set the label's value +// later, when it's convenient to do so. Once a label's value is +// known, the section class takes care of updating all previously +// appended references to it. +// +// Once all the labels to which a section refers have had their +// values determined, you can get a copy of the section's contents +// as a string. +// +// Note that there is no specified "start of section" label. This is +// because there are typically several different meanings for "the +// start of a section": the offset of the section within an object +// file, the address in memory at which the section's content appear, +// and so on. It's up to the code that uses the Section class to +// keep track of these explicitly, as they depend on the application. +class Section { + public: + Section(Endianness endianness = kUnsetEndian) + : endianness_(endianness) { }; + ~Section() { }; + + // Set the default endianness of this section to ENDIANNESS. This + // sets the behavior of the D appending functions. If the + // assembler's default endianness was set, this is the + void set_endianness(Endianness endianness) { + endianness_ = endianness; + } + + // Return the default endianness of this section. + Endianness endianness() const { return endianness_; } + + // Append the SIZE bytes at DATA or the contents of STRING to the + // end of this section. Return a reference to this section. + Section &Append(const u_int8_t *data, size_t size) { + contents_.append(reinterpret_cast(data), size); + return *this; + }; + Section &Append(const string &data) { + contents_.append(data); + return *this; + }; + + // Append SIZE copies of BYTE to the end of this section. Return a + // reference to this section. + Section &Append(size_t size, u_int8_t byte) { + contents_.append(size, (char) byte); + return *this; + } + + // Append NUMBER to this section. ENDIANNESS is the endianness to + // use to write the number. SIZE is the length of the number in + // bytes. Return a reference to this section. + Section &Append(Endianness endianness, size_t size, u_int64_t number); + Section &Append(Endianness endianness, size_t size, const Label &label); + + // Append SECTION to the end of this section. The labels SECTION + // refers to need not be defined yet. + // + // Note that this has no effect on any Labels' values, or on + // SECTION. If placing SECTION within 'this' provides new + // constraints on existing labels' values, then it's up to the + // caller to fiddle with those labels as needed. + Section &Append(const Section §ion); + + // Append the contents of DATA as a series of bytes terminated by + // a NULL character. + Section &AppendCString(const string &data) { + Append(data); + contents_ += '\0'; + return *this; + } + + // Append VALUE or LABEL to this section, with the given bit width and + // endianness. Return a reference to this section. + // + // The names of these functions have the form : + // is either 'L' (little-endian, least significant byte first), + // 'B' (big-endian, most significant byte first), or + // 'D' (default, the section's default endianness) + // is 8, 16, 32, or 64. + // + // Since endianness doesn't matter for a single byte, all the + // =8 functions are equivalent. + // + // These can be used to write both signed and unsigned values, as + // the compiler will properly sign-extend a signed value before + // passing it to the function, at which point the function's + // behavior is the same either way. + Section &L8(u_int8_t value) { contents_ += value; return *this; } + Section &B8(u_int8_t value) { contents_ += value; return *this; } + Section &D8(u_int8_t value) { contents_ += value; return *this; } + Section &L16(u_int16_t), &L32(u_int32_t), &L64(u_int64_t), + &B16(u_int16_t), &B32(u_int32_t), &B64(u_int64_t), + &D16(u_int16_t), &D32(u_int32_t), &D64(u_int64_t); + Section &L8(const Label &label), &L16(const Label &label), + &L32(const Label &label), &L64(const Label &label), + &B8(const Label &label), &B16(const Label &label), + &B32(const Label &label), &B64(const Label &label), + &D8(const Label &label), &D16(const Label &label), + &D32(const Label &label), &D64(const Label &label); + + // Append VALUE in a signed LEB128 (Little-Endian Base 128) form. + // + // The signed LEB128 representation of an integer N is a variable + // number of bytes: + // + // - If N is between -0x40 and 0x3f, then its signed LEB128 + // representation is a single byte whose value is N. + // + // - Otherwise, its signed LEB128 representation is (N & 0x7f) | + // 0x80, followed by the signed LEB128 representation of N / 128, + // rounded towards negative infinity. + // + // In other words, we break VALUE into groups of seven bits, put + // them in little-endian order, and then write them as eight-bit + // bytes with the high bit on all but the last. + // + // Note that VALUE cannot be a Label (we would have to implement + // relaxation). + Section &LEB128(long long value); + + // Append VALUE in unsigned LEB128 (Little-Endian Base 128) form. + // + // The unsigned LEB128 representation of an integer N is a variable + // number of bytes: + // + // - If N is between 0 and 0x7f, then its unsigned LEB128 + // representation is a single byte whose value is N. + // + // - Otherwise, its unsigned LEB128 representation is (N & 0x7f) | + // 0x80, followed by the unsigned LEB128 representation of N / + // 128, rounded towards negative infinity. + // + // Note that VALUE cannot be a Label (we would have to implement + // relaxation). + Section &ULEB128(u_int64_t value); + + // Jump to the next location aligned on an ALIGNMENT-byte boundary, + // relative to the start of the section. Fill the gap with PAD_BYTE. + // ALIGNMENT must be a power of two. Return a reference to this + // section. + Section &Align(size_t alignment, u_int8_t pad_byte = 0); + + // Clear the contents of this section. + void Clear(); + + // Return the current size of the section. + size_t Size() const { return contents_.size(); } + + // Return a label representing the start of the section. + // + // It is up to the user whether this label represents the section's + // position in an object file, the section's address in memory, or + // what have you; some applications may need both, in which case + // this simple-minded interface won't be enough. This class only + // provides a single start label, for use with the Here and Mark + // member functions. + // + // Ideally, we'd provide this in a subclass that actually knows more + // about the application at hand and can provide an appropriate + // collection of start labels. But then the appending member + // functions like Append and D32 would return a reference to the + // base class, not the derived class, and the chaining won't work. + // Since the only value here is in pretty notation, that's a fatal + // flaw. + Label start() const { return start_; } + + // Return a label representing the point at which the next Appended + // item will appear in the section, relative to start(). + Label Here() const { return start_ + Size(); } + + // Set *LABEL to Here, and return a reference to this section. + Section &Mark(Label *label) { *label = Here(); return *this; } + + // If there are no undefined label references left in this + // section, set CONTENTS to the contents of this section, as a + // string, and clear this section. Return true on success, or false + // if there were still undefined labels. + bool GetContents(string *contents); + + private: + // Used internally. A reference to a label's value. + struct Reference { + Reference(size_t set_offset, Endianness set_endianness, size_t set_size, + const Label &set_label) + : offset(set_offset), endianness(set_endianness), size(set_size), + label(set_label) { } + + // The offset of the reference within the section. + size_t offset; + + // The endianness of the reference. + Endianness endianness; + + // The size of the reference. + size_t size; + + // The label to which this is a reference. + Label label; + }; + + // The default endianness of this section. + Endianness endianness_; + + // The contents of the section. + string contents_; + + // References to labels within those contents. + vector references_; + + // A label referring to the beginning of the section. + Label start_; +}; + +} // namespace TestAssembler +} // namespace google_breakpad + +#endif // PROCESSOR_TEST_ASSEMBLER_H_ diff --git a/src/processor/test_assembler_unittest.cc b/src/processor/test_assembler_unittest.cc new file mode 100644 index 00000000..97009605 --- /dev/null +++ b/src/processor/test_assembler_unittest.cc @@ -0,0 +1,1644 @@ +// Copyright (c) 2010, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Original author: Jim Blandy + +// test_assembler_unittest.cc: Unit tests for google_breakpad::TestAssembler. + +#include +#include + +#include "breakpad_googletest_includes.h" +#include "processor/test_assembler.h" + +using google_breakpad::TestAssembler::Label; +using google_breakpad::TestAssembler::Section; +using google_breakpad::TestAssembler::kBigEndian; +using google_breakpad::TestAssembler::kLittleEndian; +using std::string; +using testing::Test; + +TEST(ConstructLabel, Simple) { + Label l; +} + +TEST(ConstructLabel, Undefined) { + Label l; + EXPECT_FALSE(l.IsKnownConstant()); +} + +TEST(ConstructLabelDeathTest, Undefined) { + Label l; + ASSERT_DEATH(l.Value(), "IsKnownConstant\\(&v\\)"); +} + +TEST(ConstructLabel, Constant) { + Label l(0x060b9f974eaf301eULL); + u_int64_t v; + EXPECT_TRUE(l.IsKnownConstant(&v)); + EXPECT_EQ(v, 0x060b9f974eaf301eULL); + EXPECT_EQ(l.Value(), 0x060b9f974eaf301eULL); +} + +TEST(ConstructLabel, Copy) { + Label l; + Label m(l); + u_int64_t v; + EXPECT_TRUE(l.IsKnownOffsetFrom(m, &v)); + EXPECT_EQ(0U, v); +} + +// The left-hand-side of a label assignment can be either +// unconstrained, related, or known. The right-hand-side can be any of +// those, or an integer. +TEST(Assignment, UnconstrainedToUnconstrained) { + Label l, m; + l = m; + EXPECT_EQ(0U, l-m); + EXPECT_TRUE(l.IsKnownOffsetFrom(m)); + u_int64_t d; + EXPECT_TRUE(l.IsKnownOffsetFrom(m, &d)); + EXPECT_EQ(0U, d); + EXPECT_FALSE(l.IsKnownConstant()); +} + +TEST(Assignment, UnconstrainedToRelated) { + Label l, m, n; + l = n; + l = m; + EXPECT_EQ(0U, l-m); + EXPECT_TRUE(l.IsKnownOffsetFrom(m)); + u_int64_t d; + EXPECT_TRUE(l.IsKnownOffsetFrom(m, &d)); + EXPECT_EQ(0U, d); + EXPECT_FALSE(l.IsKnownConstant()); +} + +TEST(Assignment, UnconstrainedToKnown) { + Label l, m; + l = 0x8fd16e55b20a39c1ULL; + l = m; + EXPECT_EQ(0U, l-m); + EXPECT_TRUE(l.IsKnownOffsetFrom(m)); + u_int64_t d; + EXPECT_TRUE(l.IsKnownOffsetFrom(m, &d)); + EXPECT_EQ(0U, d); + EXPECT_TRUE(m.IsKnownConstant()); + EXPECT_EQ(0x8fd16e55b20a39c1ULL, m.Value()); +} + +TEST(Assignment, RelatedToUnconstrained) { + Label l, m, n; + m = n; + l = m; + EXPECT_EQ(0U, l-n); + EXPECT_TRUE(l.IsKnownOffsetFrom(n)); + u_int64_t d; + EXPECT_TRUE(l.IsKnownOffsetFrom(n, &d)); + EXPECT_EQ(0U, d); + EXPECT_FALSE(l.IsKnownConstant()); +} + +TEST(Assignment, RelatedToRelated) { + Label l, m, n, o; + l = n; + m = o; + l = m; + EXPECT_EQ(0U, n-o); + EXPECT_TRUE(n.IsKnownOffsetFrom(o)); + u_int64_t d; + EXPECT_TRUE(n.IsKnownOffsetFrom(o, &d)); + EXPECT_EQ(0U, d); + EXPECT_FALSE(l.IsKnownConstant()); +} + +TEST(Assignment, RelatedToKnown) { + Label l, m, n; + m = n; + l = 0xd2011f8c82ad56f2ULL; + l = m; + EXPECT_TRUE(l.IsKnownConstant()); + EXPECT_EQ(0xd2011f8c82ad56f2ULL, l.Value()); + EXPECT_TRUE(m.IsKnownConstant()); + EXPECT_EQ(0xd2011f8c82ad56f2ULL, m.Value()); + EXPECT_TRUE(n.IsKnownConstant()); + EXPECT_EQ(0xd2011f8c82ad56f2ULL, n.Value()); +} + +TEST(Assignment, KnownToUnconstrained) { + Label l, m; + m = 0x50b024c0d6073887ULL; + l = m; + EXPECT_TRUE(l.IsKnownConstant()); + EXPECT_EQ(0x50b024c0d6073887ULL, l.Value()); + EXPECT_TRUE(m.IsKnownConstant()); + EXPECT_EQ(0x50b024c0d6073887ULL, m.Value()); +} + +TEST(Assignment, KnownToRelated) { + Label l, m, n; + l = n; + m = 0x5348883655c727e5ULL; + l = m; + EXPECT_TRUE(l.IsKnownConstant()); + EXPECT_EQ(0x5348883655c727e5ULL, l.Value()); + EXPECT_TRUE(m.IsKnownConstant()); + EXPECT_EQ(0x5348883655c727e5ULL, m.Value()); + EXPECT_TRUE(n.IsKnownConstant()); + EXPECT_EQ(0x5348883655c727e5ULL, n.Value()); +} + +TEST(Assignment, KnownToKnown) { + Label l, m; + l = 0x36c209c20987564eULL; + m = 0x36c209c20987564eULL; + l = m; + EXPECT_TRUE(l.IsKnownConstant()); + EXPECT_EQ(0x36c209c20987564eULL, l.Value()); + EXPECT_TRUE(m.IsKnownConstant()); + EXPECT_EQ(0x36c209c20987564eULL, m.Value()); +} + +TEST(Assignment, ConstantToUnconstrained) { + Label l; + l = 0xc02495f4d7f5a957ULL; + EXPECT_TRUE(l.IsKnownConstant()); + EXPECT_EQ(0xc02495f4d7f5a957ULL, l.Value()); +} + +TEST(Assignment, ConstantToRelated) { + Label l, m; + l = m; + l = 0x4577901cf275488dULL; + EXPECT_TRUE(l.IsKnownConstant()); + EXPECT_EQ(0x4577901cf275488dULL, l.Value()); + EXPECT_TRUE(m.IsKnownConstant()); + EXPECT_EQ(0x4577901cf275488dULL, m.Value()); +} + +TEST(Assignment, ConstantToKnown) { + Label l; + l = 0xec0b9c369b7e8ea7ULL; + l = 0xec0b9c369b7e8ea7ULL; + EXPECT_TRUE(l.IsKnownConstant()); + EXPECT_EQ(0xec0b9c369b7e8ea7ULL, l.Value()); +} + +TEST(AssignmentDeathTest, Self) { + Label l; + ASSERT_DEATH(l = l, "binding != this"); +} + +TEST(AssignmentDeathTest, IndirectCycle) { + Label l, m, n; + l = m; + m = n; + ASSERT_DEATH(n = l, "binding != this"); +} + +TEST(AssignmentDeathTest, Cycle) { + Label l, m, n, o; + l = m; + m = n; + o = n; + ASSERT_DEATH(o = l, "binding != this"); +} + +TEST(Addition, LabelConstant) { + Label l, m; + m = l + 0x5248d93e8bbe9497ULL; + EXPECT_TRUE(m.IsKnownOffsetFrom(l)); + u_int64_t d; + EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d)); + EXPECT_EQ(0x5248d93e8bbe9497ULL, d); + EXPECT_FALSE(m.IsKnownConstant()); +} + +TEST(Addition, ConstantLabel) { + Label l, m; + m = 0xf51e94e00d6e3c84ULL + l; + EXPECT_TRUE(m.IsKnownOffsetFrom(l)); + u_int64_t d; + EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d)); + EXPECT_EQ(0xf51e94e00d6e3c84ULL, d); + EXPECT_FALSE(m.IsKnownConstant()); +} + +TEST(Addition, KnownLabelConstant) { + Label l, m; + l = 0x16286307042ce0d8ULL; + m = l + 0x3fdddd91306719d7ULL; + EXPECT_TRUE(m.IsKnownOffsetFrom(l)); + u_int64_t d; + EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d)); + EXPECT_EQ(0x3fdddd91306719d7ULL, d); + EXPECT_TRUE(m.IsKnownConstant()); + EXPECT_EQ(0x16286307042ce0d8ULL + 0x3fdddd91306719d7ULL, m.Value()); +} + +TEST(Addition, ConstantKnownLabel) { + Label l, m; + l = 0x50f62d0cdd1031deULL; + m = 0x1b13462d8577c538ULL + l; + EXPECT_TRUE(m.IsKnownOffsetFrom(l)); + u_int64_t d; + EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d)); + EXPECT_EQ(0x1b13462d8577c538ULL, d); + EXPECT_TRUE(m.IsKnownConstant()); + EXPECT_EQ(0x50f62d0cdd1031deULL + 0x1b13462d8577c538ULL, m.Value()); +} + +TEST(Subtraction, LabelConstant) { + Label l, m; + m = l - 0x0620884d21d3138eULL; + EXPECT_TRUE(m.IsKnownOffsetFrom(l)); + u_int64_t d; + EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d)); + EXPECT_EQ(-0x0620884d21d3138eULL, d); + EXPECT_FALSE(m.IsKnownConstant()); +} + +TEST(Subtraction, KnownLabelConstant) { + Label l, m; + l = 0x6237fbaf9ef7929eULL; + m = l - 0x317730995d2ab6eeULL; + EXPECT_TRUE(m.IsKnownOffsetFrom(l)); + u_int64_t d; + EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d)); + EXPECT_EQ(-0x317730995d2ab6eeULL, d); + EXPECT_TRUE(m.IsKnownConstant()); + EXPECT_EQ(0x6237fbaf9ef7929eULL - 0x317730995d2ab6eeULL, m.Value()); +} + +TEST(SubtractionDeathTest, LabelLabel) { + Label l, m; + ASSERT_DEATH(l - m, "IsKnownOffsetFrom\\(label, &offset\\)"); +} + +TEST(Subtraction, LabelLabel) { + Label l, m; + l = m + 0x7fa77ec63e28a17aULL; + EXPECT_EQ(0x7fa77ec63e28a17aULL, l - m); + EXPECT_EQ(-0x7fa77ec63e28a17aULL, m - l); +} + +TEST(IsKnownConstant, Undefined) { + Label l; + EXPECT_FALSE(l.IsKnownConstant()); +} + +TEST(IsKnownConstant, RelatedLabel) { + Label l, m; + l = m; + EXPECT_FALSE(l.IsKnownConstant()); + EXPECT_FALSE(m.IsKnownConstant()); +} + +TEST(IsKnownConstant, Constant) { + Label l; + l = 0xf374b1bdd6a22576ULL; + EXPECT_TRUE(l.IsKnownConstant()); +} + +TEST(IsKnownOffsetFrom, Unrelated) { + Label l, m; + EXPECT_FALSE(l.IsKnownOffsetFrom(m)); +} + +TEST(IsKnownOffsetFrom, Related) { + Label l, m; + l = m; + EXPECT_TRUE(l.IsKnownOffsetFrom(m)); +} + +// Test the construction of chains of related labels, and the +// propagation of values through them. +// +// Although the relations between labels are supposed to behave +// symmetrically --- that is, 'a = b' should put a and b in +// indistinguishable states --- there's a distinction made internally +// between the target (a) and the source (b). +// +// So there are five test axes to cover: +// +// - Do we construct the chain with assignment ("Assign") or with constructors +// ("Construct")? +// +// - Do we set the value of the label at the start of the chain +// ("Start") or the label at the end ("End")? +// +// - Are we testing the propagation of a relationship between variable +// values ("Relation"), or the propagation of a known constant value +// ("Value")? +// +// - Do we set the value before building the chain ("Before") or after +// the chain has been built ("After")? +// +// - Do we add new relationships to the end of the existing chain +// ("Forward") or to the beginning ("Backward")? +// +// Of course, "Construct" and "Backward" can't be combined, which +// eliminates eight combinations, and "Construct", "End", and "Before" +// can't be combined, which eliminates two more, so there are are 22 +// combinations, not 32. + +TEST(LabelChain, AssignStartRelationBeforeForward) { + Label a, b, c, d; + Label x; + a = x; + b = a + 0x1; + c = b + 0x10; + d = c + 0x100; + EXPECT_EQ(0x111U, d-x); + EXPECT_EQ(0x11U, c-x); + EXPECT_EQ(0x1U, b-x); + EXPECT_EQ(0U, a-x); +} + +TEST(LabelChain, AssignStartRelationBeforeBackward) { + Label a, b, c, d; + Label x; + a = x; + d = c + 0x100; + c = b + 0x10; + b = a + 0x1; + EXPECT_EQ(0x111U, d-x); + EXPECT_EQ(0x11U, c-x); + EXPECT_EQ(0x1U, b-x); + EXPECT_EQ(0U, a-x); +} + +TEST(LabelChain, AssignStartRelationAfterForward) { + Label a, b, c, d; + Label x; + b = a + 0x1; + c = b + 0x10; + d = c + 0x100; + a = x; + EXPECT_EQ(0x111U, d-x); + EXPECT_EQ(0x11U, c-x); + EXPECT_EQ(0x1U, b-x); + EXPECT_EQ(0U, a-x); +} + +TEST(LabelChain, AssignStartRelationAfterBackward) { + Label a, b, c, d; + Label x; + d = c + 0x100; + c = b + 0x10; + b = a + 0x1; + a = x; + EXPECT_EQ(0x111U, d-x); + EXPECT_EQ(0x11U, c-x); + EXPECT_EQ(0x1U, b-x); + EXPECT_EQ(0U, a-x); +} + +TEST(LabelChain, AssignStartValueBeforeForward) { + Label a, b, c, d; + a = 0xa131200190546ac2ULL; + b = a + 0x1; + c = b + 0x10; + d = c + 0x100; + EXPECT_EQ(0xa131200190546ac2ULL + 0x111U, d.Value()); + EXPECT_EQ(0xa131200190546ac2ULL + 0x11U, c.Value()); + EXPECT_EQ(0xa131200190546ac2ULL + 0x1U, b.Value()); + EXPECT_EQ(0xa131200190546ac2ULL + 0U, a.Value()); +} + +TEST(LabelChain, AssignStartValueBeforeBackward) { + Label a, b, c, d; + a = 0x8da17e1670ad4fa2ULL; + d = c + 0x100; + c = b + 0x10; + b = a + 0x1; + EXPECT_EQ(0x8da17e1670ad4fa2ULL + 0x111U, d.Value()); + EXPECT_EQ(0x8da17e1670ad4fa2ULL + 0x11U, c.Value()); + EXPECT_EQ(0x8da17e1670ad4fa2ULL + 0x1U, b.Value()); + EXPECT_EQ(0x8da17e1670ad4fa2ULL + 0U, a.Value()); +} + +TEST(LabelChain, AssignStartValueAfterForward) { + Label a, b, c, d; + b = a + 0x1; + c = b + 0x10; + d = c + 0x100; + a = 0x99b8f51bafd41adaULL; + EXPECT_EQ(0x99b8f51bafd41adaULL + 0x111U, d.Value()); + EXPECT_EQ(0x99b8f51bafd41adaULL + 0x11U, c.Value()); + EXPECT_EQ(0x99b8f51bafd41adaULL + 0x1U, b.Value()); + EXPECT_EQ(0x99b8f51bafd41adaULL + 0U, a.Value()); +} + +TEST(LabelChain, AssignStartValueAfterBackward) { + Label a, b, c, d; + d = c + 0x100; + c = b + 0x10; + b = a + 0x1; + a = 0xc86ca1d97ab5df6eULL; + EXPECT_EQ(0xc86ca1d97ab5df6eULL + 0x111U, d.Value()); + EXPECT_EQ(0xc86ca1d97ab5df6eULL + 0x11U, c.Value()); + EXPECT_EQ(0xc86ca1d97ab5df6eULL + 0x1U, b.Value()); + EXPECT_EQ(0xc86ca1d97ab5df6eULL + 0U, a.Value()); +} + +TEST(LabelChain, AssignEndRelationBeforeForward) { + Label a, b, c, d; + Label x; + x = d; + b = a + 0x1; + c = b + 0x10; + d = c + 0x100; + EXPECT_EQ(-(u_int64_t)0x111U, a-x); + EXPECT_EQ(-(u_int64_t)0x110U, b-x); + EXPECT_EQ(-(u_int64_t)0x100U, c-x); + EXPECT_EQ(-(u_int64_t)0U, d-x); +} + +TEST(LabelChain, AssignEndRelationBeforeBackward) { + Label a, b, c, d; + Label x; + x = d; + d = c + 0x100; + c = b + 0x10; + b = a + 0x1; + EXPECT_EQ(-(u_int64_t)0x111U, a-x); + EXPECT_EQ(-(u_int64_t)0x110U, b-x); + EXPECT_EQ(-(u_int64_t)0x100U, c-x); + EXPECT_EQ(-(u_int64_t)0U, d-x); +} + +TEST(LabelChain, AssignEndRelationAfterForward) { + Label a, b, c, d; + Label x; + b = a + 0x1; + c = b + 0x10; + d = c + 0x100; + x = d; + EXPECT_EQ(-(u_int64_t)0x111U, a-x); + EXPECT_EQ(-(u_int64_t)0x110U, b-x); + EXPECT_EQ(-(u_int64_t)0x100U, c-x); + EXPECT_EQ(-(u_int64_t)0x000U, d-x); +} + +TEST(LabelChain, AssignEndRelationAfterBackward) { + Label a, b, c, d; + Label x; + d = c + 0x100; + c = b + 0x10; + b = a + 0x1; + x = d; + EXPECT_EQ(-(u_int64_t)0x111U, a-x); + EXPECT_EQ(-(u_int64_t)0x110U, b-x); + EXPECT_EQ(-(u_int64_t)0x100U, c-x); + EXPECT_EQ(-(u_int64_t)0x000U, d-x); +} + +TEST(LabelChain, AssignEndValueBeforeForward) { + Label a, b, c, d; + d = 0xa131200190546ac2ULL; + b = a + 0x1; + c = b + 0x10; + d = c + 0x100; + EXPECT_EQ(0xa131200190546ac2ULL - 0x111, a.Value()); + EXPECT_EQ(0xa131200190546ac2ULL - 0x110, b.Value()); + EXPECT_EQ(0xa131200190546ac2ULL - 0x100, c.Value()); + EXPECT_EQ(0xa131200190546ac2ULL - 0x000, d.Value()); +} + +TEST(LabelChain, AssignEndValueBeforeBackward) { + Label a, b, c, d; + d = 0x8da17e1670ad4fa2ULL; + d = c + 0x100; + c = b + 0x10; + b = a + 0x1; + EXPECT_EQ(0x8da17e1670ad4fa2ULL - 0x111, a.Value()); + EXPECT_EQ(0x8da17e1670ad4fa2ULL - 0x110, b.Value()); + EXPECT_EQ(0x8da17e1670ad4fa2ULL - 0x100, c.Value()); + EXPECT_EQ(0x8da17e1670ad4fa2ULL - 0x000, d.Value()); +} + +TEST(LabelChain, AssignEndValueAfterForward) { + Label a, b, c, d; + b = a + 0x1; + c = b + 0x10; + d = c + 0x100; + d = 0x99b8f51bafd41adaULL; + EXPECT_EQ(0x99b8f51bafd41adaULL - 0x111, a.Value()); + EXPECT_EQ(0x99b8f51bafd41adaULL - 0x110, b.Value()); + EXPECT_EQ(0x99b8f51bafd41adaULL - 0x100, c.Value()); + EXPECT_EQ(0x99b8f51bafd41adaULL - 0x000, d.Value()); +} + +TEST(LabelChain, AssignEndValueAfterBackward) { + Label a, b, c, d; + d = c + 0x100; + c = b + 0x10; + b = a + 0x1; + d = 0xc86ca1d97ab5df6eULL; + EXPECT_EQ(0xc86ca1d97ab5df6eULL - 0x111, a.Value()); + EXPECT_EQ(0xc86ca1d97ab5df6eULL - 0x110, b.Value()); + EXPECT_EQ(0xc86ca1d97ab5df6eULL - 0x100, c.Value()); + EXPECT_EQ(0xc86ca1d97ab5df6eULL - 0x000, d.Value()); +} + +TEST(LabelChain, ConstructStartRelationBeforeForward) { + Label x; + Label a(x); + Label b(a + 0x1); + Label c(b + 0x10); + Label d(c + 0x100); + EXPECT_EQ(0x111U, d-x); + EXPECT_EQ(0x11U, c-x); + EXPECT_EQ(0x1U, b-x); + EXPECT_EQ(0U, a-x); +} + +TEST(LabelChain, ConstructStartRelationAfterForward) { + Label x; + Label a; + Label b(a + 0x1); + Label c(b + 0x10); + Label d(c + 0x100); + a = x; + EXPECT_EQ(0x111U, d-x); + EXPECT_EQ(0x11U, c-x); + EXPECT_EQ(0x1U, b-x); + EXPECT_EQ(0U, a-x); +} + +TEST(LabelChain, ConstructStartValueBeforeForward) { + Label a(0x5d234d177d01ccc8ULL); + Label b(a + 0x1); + Label c(b + 0x10); + Label d(c + 0x100); + EXPECT_EQ(0x5d234d177d01ccc8ULL + 0x111U, d.Value()); + EXPECT_EQ(0x5d234d177d01ccc8ULL + 0x011U, c.Value()); + EXPECT_EQ(0x5d234d177d01ccc8ULL + 0x001U, b.Value()); + EXPECT_EQ(0x5d234d177d01ccc8ULL + 0x000U, a.Value()); +} + +TEST(LabelChain, ConstructStartValueAfterForward) { + Label a; + Label b(a + 0x1); + Label c(b + 0x10); + Label d(c + 0x100); + a = 0xded85d54586e84fcULL; + EXPECT_EQ(0xded85d54586e84fcULL + 0x111U, d.Value()); + EXPECT_EQ(0xded85d54586e84fcULL + 0x011U, c.Value()); + EXPECT_EQ(0xded85d54586e84fcULL + 0x001U, b.Value()); + EXPECT_EQ(0xded85d54586e84fcULL + 0x000U, a.Value()); +} + +TEST(LabelChain, ConstructEndRelationAfterForward) { + Label x; + Label a; + Label b(a + 0x1); + Label c(b + 0x10); + Label d(c + 0x100); + x = d; + EXPECT_EQ(-(u_int64_t)0x111U, a-x); + EXPECT_EQ(-(u_int64_t)0x110U, b-x); + EXPECT_EQ(-(u_int64_t)0x100U, c-x); + EXPECT_EQ(-(u_int64_t)0x000U, d-x); +} + +TEST(LabelChain, ConstructEndValueAfterForward) { + Label a; + Label b(a + 0x1); + Label c(b + 0x10); + Label d(c + 0x100); + d = 0x99b8f51bafd41adaULL; + EXPECT_EQ(0x99b8f51bafd41adaULL - 0x111, a.Value()); + EXPECT_EQ(0x99b8f51bafd41adaULL - 0x110, b.Value()); + EXPECT_EQ(0x99b8f51bafd41adaULL - 0x100, c.Value()); + EXPECT_EQ(0x99b8f51bafd41adaULL - 0x000, d.Value()); +} + +TEST(LabelTree, KnownValue) { + Label l, m, n, o, p; + l = m; + m = n; + o = p; + p = n; + l = 0x536b5de3d468a1b5ULL; + EXPECT_EQ(0x536b5de3d468a1b5ULL, o.Value()); +} + +TEST(LabelTree, Related) { + Label l, m, n, o, p; + l = m - 1; + m = n - 10; + o = p + 100; + p = n + 1000; + EXPECT_EQ(1111U, o - l); +} + +TEST(EquationDeathTest, EqualConstants) { + Label m = 0x0d3962f280f07d24ULL; + Label n = 0x0d3962f280f07d24ULL; + m = n; // no death expected +} + +TEST(EquationDeathTest, EqualIndirectConstants) { + Label m = 0xa347f1e5238fe6a1ULL; + Label n; + Label o = n; + n = 0xa347f1e5238fe6a1ULL; + n = m; // no death expected +} + +TEST(EquationDeathTest, ConstantClash) { + Label m = 0xd4cc0f4f630ec741ULL; + Label n = 0x934cd2d8254fc3eaULL; + ASSERT_DEATH(m = n, "addend_ == addend"); +} + +TEST(EquationDeathTest, IndirectConstantClash) { + Label m = 0xd4cc0f4f630ec741ULL; + Label n, o; + n = o; + o = 0xcfbe3b83ac49ce86ULL; + ASSERT_DEATH(m = n, "addend_ == addend"); +} + +// Assigning to a related label may free the next Binding on its +// chain. This test always passes; it is interesting to memory +// checkers and coverage analysis. +TEST(LabelReferenceCount, AssignmentFree) { + Label l; + { + Label m; + l = m; + } + // This should free m's Binding. + l = 0xca8bae92f0376d4fULL; + ASSERT_EQ(0xca8bae92f0376d4fULL, l.Value()); +} + +// Finding the value of a label may free the Binding it refers to. This test +// always passes; it is interesting to memory checkers and coverage analysis. +TEST(LabelReferenceCount, FindValueFree) { + Label l; + { + Label m, n; + l = m; + m = n; + n = 0x7a0b0c576672daafULL; + // At this point, l's Binding refers to m's Binding, which refers + // to n's binding. + } + // Now, l is the only reference keeping the three Bindings alive. + // Resolving its value should free l's and m's original bindings. + ASSERT_EQ(0x7a0b0c576672daafULL, l.Value()); +} + +TEST(ConstructSection, Simple) { + Section s; +} + +TEST(ConstructSection, WithEndian) { + Section s(kBigEndian); +} + +// A fixture class for TestAssembler::Section tests. +class SectionFixture { + public: + Section section; + string contents; + static const u_int8_t data[]; + static const size_t data_size; +}; + +const u_int8_t SectionFixture::data[] = { + 0x87, 0x4f, 0x43, 0x67, 0x30, 0xd0, 0xd4, 0x0e +}; + +#define I0() +#define I1(a) { a } +#define I2(a,b) { a,b } +#define I3(a,b,c) { a,b,c } +#define I4(a,b,c,d) { a,b,c,d } +#define I5(a,b,c,d,e) { a,b,c,d,e } +#define I6(a,b,c,d,e,f) { a,b,c,d,e,f } +#define I7(a,b,c,d,e,f,g) { a,b,c,d,e,f,g } +#define I8(a,b,c,d,e,f,g,h) { a,b,c,d,e,f,g,h } +#define I9(a,b,c,d,e,f,g,h,i) { a,b,c,d,e,f,g,h,i } +#define ASSERT_BYTES(s, b) \ + do \ + { \ + static const u_int8_t expected_bytes[] = b; \ + ASSERT_EQ(sizeof(expected_bytes), s.size()); \ + ASSERT_TRUE(memcmp(s.data(), (const char *) expected_bytes, \ + sizeof(expected_bytes)) == 0); \ + } \ + while(0) + +class Append: public SectionFixture, public Test { }; + +TEST_F(Append, Bytes) { + section.Append(data, sizeof(data)); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_EQ(sizeof(data), contents.size()); + EXPECT_TRUE(0 == memcmp(contents.data(), (const char *) data, sizeof(data))); +} + +TEST_F(Append, BytesTwice) { + section.Append(data, sizeof(data)); + section.Append(data, sizeof(data)); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_EQ(2 * sizeof(data), contents.size()); + ASSERT_TRUE(0 == memcmp(contents.data(), (const char *) data, sizeof(data))); + ASSERT_TRUE(0 == memcmp(contents.data() + sizeof(data), + (const char *) data, sizeof(data))); +} + +TEST_F(Append, String) { + string s1 = "howdy "; + string s2 = "there"; + section.Append(s1); + section.Append(s2); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_STREQ(contents.c_str(), "howdy there"); +} + +TEST_F(Append, RepeatedBytes) { + section.Append((size_t) 10, '*'); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_STREQ(contents.c_str(), "**********"); +} + +TEST_F(Append, GeneralLE1) { + section.Append(kLittleEndian, 1, 42); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I1(42)); +} + +TEST_F(Append, GeneralLE2) { + section.Append(kLittleEndian, 2, 0x15a1); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I2(0xa1, 0x15)); +} + +TEST_F(Append, GeneralLE3) { + section.Append(kLittleEndian, 3, 0x59ae8d); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I3(0x8d, 0xae, 0x59)); +} + +TEST_F(Append, GeneralLE4) { + section.Append(kLittleEndian, 4, 0x51603c56); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I4(0x56, 0x3c, 0x60, 0x51)); +} + +TEST_F(Append, GeneralLE5) { + section.Append(kLittleEndian, 5, 0x385e2803b4ULL); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I5(0xb4, 0x03, 0x28, 0x5e, 0x38)); +} + +TEST_F(Append, GeneralLE6) { + section.Append(kLittleEndian, 6, 0xc7db9534dd1fULL); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I6(0x1f, 0xdd, 0x34, 0x95, 0xdb, 0xc7)); +} + +TEST_F(Append, GeneralLE7) { + section.Append(kLittleEndian, 7, 0x1445c9f1b843e6ULL); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I7(0xe6, 0x43, 0xb8, 0xf1, 0xc9, 0x45, 0x14)); +} + +TEST_F(Append, GeneralLE8) { + section.Append(kLittleEndian, 8, 0xaf48019dfe5c01e5ULL); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I8(0xe5, 0x01, 0x5c, 0xfe, 0x9d, 0x01, 0x48, 0xaf)); +} + +TEST_F(Append, GeneralBE1) { + section.Append(kBigEndian, 1, 0xd0ULL); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I1(0xd0)); +} + +TEST_F(Append, GeneralBE2) { + section.Append(kBigEndian, 2, 0x2e7eULL); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I2(0x2e, 0x7e)); +} + +TEST_F(Append, GeneralBE3) { + section.Append(kBigEndian, 3, 0x37dad6ULL); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I3(0x37, 0xda, 0xd6)); +} + +TEST_F(Append, GeneralBE4) { + section.Append(kBigEndian, 4, 0x715935c7ULL); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I4(0x71, 0x59, 0x35, 0xc7)); +} + +TEST_F(Append, GeneralBE5) { + section.Append(kBigEndian, 5, 0x42baeb02b7ULL); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I5(0x42, 0xba, 0xeb, 0x02, 0xb7)); +} + +TEST_F(Append, GeneralBE6) { + section.Append(kBigEndian, 6, 0xf1cdf10e7b18ULL); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I6(0xf1, 0xcd, 0xf1, 0x0e, 0x7b, 0x18)); +} + +TEST_F(Append, GeneralBE7) { + section.Append(kBigEndian, 7, 0xf50a724f0b0d20ULL); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I7(0xf5, 0x0a, 0x72, 0x4f, 0x0b, 0x0d, 0x20)); +} + +TEST_F(Append, GeneralBE8) { + section.Append(kBigEndian, 8, 0xa6b2cb5e98dc9c16ULL); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I8(0xa6, 0xb2, 0xcb, 0x5e, 0x98, 0xdc, 0x9c, 0x16)); +} + +TEST_F(Append, GeneralLE1Label) { + Label l; + section.Append(kLittleEndian, 1, l); + l = 42; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I1(42)); +} + +TEST_F(Append, GeneralLE2Label) { + Label l; + section.Append(kLittleEndian, 2, l); + l = 0x15a1; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I2(0xa1, 0x15)); +} + +TEST_F(Append, GeneralLE3Label) { + Label l; + section.Append(kLittleEndian, 3, l); + l = 0x59ae8d; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I3(0x8d, 0xae, 0x59)); +} + +TEST_F(Append, GeneralLE4Label) { + Label l; + section.Append(kLittleEndian, 4, l); + l = 0x51603c56; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I4(0x56, 0x3c, 0x60, 0x51)); +} + +TEST_F(Append, GeneralLE5Label) { + Label l; + section.Append(kLittleEndian, 5, l); + l = 0x385e2803b4ULL; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I5(0xb4, 0x03, 0x28, 0x5e, 0x38)); +} + +TEST_F(Append, GeneralLE6Label) { + Label l; + section.Append(kLittleEndian, 6, l); + l = 0xc7db9534dd1fULL; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I6(0x1f, 0xdd, 0x34, 0x95, 0xdb, 0xc7)); +} + +TEST_F(Append, GeneralLE7Label) { + Label l; + section.Append(kLittleEndian, 7, l); + l = 0x1445c9f1b843e6ULL; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I7(0xe6, 0x43, 0xb8, 0xf1, 0xc9, 0x45, 0x14)); +} + +TEST_F(Append, GeneralLE8Label) { + Label l; + section.Append(kLittleEndian, 8, l); + l = 0xaf48019dfe5c01e5ULL; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I8(0xe5, 0x01, 0x5c, 0xfe, 0x9d, 0x01, 0x48, 0xaf)); +} + +TEST_F(Append, GeneralBE1Label) { + Label l; + section.Append(kBigEndian, 1, l); + l = 0xd0ULL; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I1(0xd0)); +} + +TEST_F(Append, GeneralBE2Label) { + Label l; + section.Append(kBigEndian, 2, l); + l = 0x2e7eULL; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I2(0x2e, 0x7e)); +} + +TEST_F(Append, GeneralBE3Label) { + Label l; + section.Append(kBigEndian, 3, l); + l = 0x37dad6ULL; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I3(0x37, 0xda, 0xd6)); +} + +TEST_F(Append, GeneralBE4Label) { + Label l; + section.Append(kBigEndian, 4, l); + l = 0x715935c7ULL; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I4(0x71, 0x59, 0x35, 0xc7)); +} + +TEST_F(Append, GeneralBE5Label) { + Label l; + section.Append(kBigEndian, 5, l); + l = 0x42baeb02b7ULL; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I5(0x42, 0xba, 0xeb, 0x02, 0xb7)); +} + +TEST_F(Append, GeneralBE6Label) { + Label l; + section.Append(kBigEndian, 6, l); + l = 0xf1cdf10e7b18ULL; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I6(0xf1, 0xcd, 0xf1, 0x0e, 0x7b, 0x18)); +} + +TEST_F(Append, GeneralBE7Label) { + Label l; + section.Append(kBigEndian, 7, l); + l = 0xf50a724f0b0d20ULL; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I7(0xf5, 0x0a, 0x72, 0x4f, 0x0b, 0x0d, 0x20)); +} + +TEST_F(Append, GeneralBE8Label) { + Label l; + section.Append(kBigEndian, 8, l); + l = 0xa6b2cb5e98dc9c16ULL; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I8(0xa6, 0xb2, 0xcb, 0x5e, 0x98, 0xdc, 0x9c, 0x16)); +} + +TEST_F(Append, B8) { + section.Append(1, 0x2a); + section.B8(0xd3U); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I2(0x2a, 0xd3)); +} + +TEST_F(Append, B8Label) { + Label l; + section.Append(1, 0x2a); + section.B8(l); + l = 0x4bU; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I2(0x2a, 0x4b)); +} + +TEST_F(Append, B16) { + section.Append(1, 0x2a); + section.B16(0x472aU); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I3(0x2a, 0x47, 0x2a)); +} + +TEST_F(Append, B16Label) { + Label l; + section.Append(1, 0x2a); + section.B16(l); + l = 0x55e8U; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I3(0x2a, 0x55, 0xe8)); +} + +TEST_F(Append, B32) { + section.Append(1, 0x2a); + section.B32(0xbd412cbcU); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I5(0x2a, 0xbd, 0x41, 0x2c, 0xbc)); +} + +TEST_F(Append, B32Label) { + Label l; + section.Append(1, 0x2a); + section.B32(l); + l = 0x208e37d5U; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I5(0x2a, 0x20, 0x8e, 0x37, 0xd5)); +} + +TEST_F(Append, B64) { + section.Append(1, 0x2a); + section.B64(0x3402a013111e68adULL); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, + I9(0x2a, 0x34, 0x02, 0xa0, 0x13, 0x11, 0x1e, 0x68, 0xad)); +} + +TEST_F(Append, B64Label) { + Label l; + section.Append(1, 0x2a); + section.B64(l); + l = 0x355dbfbb4ac6d57fULL; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, + I9(0x2a, 0x35, 0x5d, 0xbf, 0xbb, 0x4a, 0xc6, 0xd5, 0x7f)); +} + +TEST_F(Append, L8) { + section.Append(1, 0x2a); + section.L8(0x26U); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I2(0x2a, 0x26)); +} + +TEST_F(Append, L8Label) { + Label l; + section.Append(1, 0x2a); + section.L8(l); + l = 0xa8U; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I2(0x2a, 0xa8)); +} + +TEST_F(Append, L16) { + section.Append(1, 0x2a); + section.L16(0xca6dU); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I3(0x2a, 0x6d, 0xca)); +} + +TEST_F(Append, L16Label) { + Label l; + section.Append(1, 0x2a); + section.L16(l); + l = 0xd21fU; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I3(0x2a, 0x1f, 0xd2)); +} + +TEST_F(Append, L32) { + section.Append(1, 0x2a); + section.L32(0x558f6181U); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I5(0x2a, 0x81, 0x61, 0x8f, 0x55)); +} + +TEST_F(Append, L32Label) { + Label l; + section.Append(1, 0x2a); + section.L32(l); + l = 0x4b810f82U; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I5(0x2a, 0x82, 0x0f, 0x81, 0x4b)); +} + +TEST_F(Append, L64) { + section.Append(1, 0x2a); + section.L64(0x564384f7579515bfULL); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, + I9(0x2a, 0xbf, 0x15, 0x95, 0x57, 0xf7, 0x84, 0x43, 0x56)); +} + +TEST_F(Append, L64Label) { + Label l; + section.Append(1, 0x2a); + section.L64(l); + l = 0x424b1d020667c8dbULL; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, + I9(0x2a, 0xdb, 0xc8, 0x67, 0x06, 0x02, 0x1d, 0x4b, 0x42)); +} + +TEST_F(Append, D8Big) { + section.set_endianness(kBigEndian); + section.Append(1, 0x2a); + section.D8(0xe6U); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I2(0x2a, 0xe6)); +} + +TEST_F(Append, D8BigLabel) { + Label l; + section.set_endianness(kBigEndian); + section.Append(1, 0x2a); + section.D8(l); + l = 0xeeU; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I2(0x2a, 0xee)); +} + +TEST_F(Append, D16Big) { + section.set_endianness(kBigEndian); + section.Append(1, 0x2a); + section.D16(0x83b1U); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I3(0x2a, 0x83, 0xb1)); +} + +TEST_F(Append, D16BigLabel) { + Label l; + section.set_endianness(kBigEndian); + section.Append(1, 0x2a); + section.D16(l); + l = 0x5b55U; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I3(0x2a, 0x5b, 0x55)); +} + +TEST_F(Append, D32Big) { + section.set_endianness(kBigEndian); + section.Append(1, 0x2a); + section.D32(0xd0b0e431U); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I5(0x2a, 0xd0, 0xb0, 0xe4, 0x31)); +} + +TEST_F(Append, D32BigLabel) { + Label l; + section.set_endianness(kBigEndian); + section.Append(1, 0x2a); + section.D32(l); + l = 0x312fb340U; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I5(0x2a, 0x31, 0x2f, 0xb3, 0x40)); +} + +TEST_F(Append, D64Big) { + section.set_endianness(kBigEndian); + section.Append(1, 0x2a); + section.D64(0xb109843500dbcb16ULL); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, + I9(0x2a, 0xb1, 0x09, 0x84, 0x35, 0x00, 0xdb, 0xcb, 0x16)); +} + +TEST_F(Append, D64BigLabel) { + Label l; + section.set_endianness(kBigEndian); + section.Append(1, 0x2a); + section.D64(l); + l = 0x9a0d61b70f671fd7ULL; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, + I9(0x2a, 0x9a, 0x0d, 0x61, 0xb7, 0x0f, 0x67, 0x1f, 0xd7)); +} + +TEST_F(Append, D8Little) { + section.set_endianness(kLittleEndian); + section.Append(1, 0x2a); + section.D8(0x42U); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I2(0x2a, 0x42)); +} + +TEST_F(Append, D8LittleLabel) { + Label l; + section.set_endianness(kLittleEndian); + section.Append(1, 0x2a); + section.D8(l); + l = 0x05U; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I2(0x2a, 0x05)); +} + +TEST_F(Append, D16Little) { + section.set_endianness(kLittleEndian); + section.Append(1, 0x2a); + section.D16(0xc5c5U); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I3(0x2a, 0xc5, 0xc5)); +} + +TEST_F(Append, D16LittleLabel) { + Label l; + section.set_endianness(kLittleEndian); + section.Append(1, 0x2a); + section.D16(l); + l = 0xb620U; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I3(0x2a, 0x20, 0xb6)); +} + +TEST_F(Append, D32Little) { + section.set_endianness(kLittleEndian); + section.Append(1, 0x2a); + section.D32(0x1a87d0feU); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I5(0x2a, 0xfe, 0xd0, 0x87, 0x1a)); +} + +TEST_F(Append, D32LittleLabel) { + Label l; + section.set_endianness(kLittleEndian); + section.Append(1, 0x2a); + section.D32(l); + l = 0xb8012d6bU; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I5(0x2a, 0x6b, 0x2d, 0x01, 0xb8)); +} + +TEST_F(Append, D64Little) { + section.set_endianness(kLittleEndian); + section.Append(1, 0x2a); + section.D64(0x42de75c61375a1deULL); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, + I9(0x2a, 0xde, 0xa1, 0x75, 0x13, 0xc6, 0x75, 0xde, 0x42)); +} + +TEST_F(Append, D64LittleLabel) { + Label l; + section.set_endianness(kLittleEndian); + section.Append(1, 0x2a); + section.D64(l); + l = 0x8b3bececf3fb5312ULL; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, + I9(0x2a, 0x12, 0x53, 0xfb, 0xf3, 0xec, 0xec, 0x3b, 0x8b)); +} + +TEST_F(Append, Variety) { + Label a, b, c, d, e, f, g, h; + section.Append(kBigEndian, 1, a) + .Append(kLittleEndian, 8, h) + .Append(kBigEndian, 1, 0x8bULL) + .Append(kLittleEndian, 8, 0x0ea56540448f4439ULL) + .Append(kBigEndian, 2, b) + .Append(kLittleEndian, 7, g) + .Append(kBigEndian, 2, 0xcf15ULL) + .Append(kLittleEndian, 7, 0x29694f04c5724aULL) + .Append(kBigEndian, 3, c) + .Append(kLittleEndian, 6, f) + .Append(kBigEndian, 3, 0x8c3ffdULL) + .Append(kLittleEndian, 6, 0x6f11ba80187aULL) + .Append(kBigEndian, 4, d) + .Append(kLittleEndian, 5, e) + .Append(kBigEndian, 4, 0x2fda2472ULL) + .Append(kLittleEndian, 5, 0x0aa02d423fULL) + .Append(kBigEndian, 5, e) + .Append(kLittleEndian, 4, d) + .Append(kBigEndian, 5, 0x53ba432138ULL) + .Append(kLittleEndian, 4, 0xf139ae60ULL) + .Append(kBigEndian, 6, f) + .Append(kLittleEndian, 3, c) + .Append(kBigEndian, 6, 0x168e436af716ULL) + .Append(kLittleEndian, 3, 0x3ef189ULL) + .Append(kBigEndian, 7, g) + .Append(kLittleEndian, 2, b) + .Append(kBigEndian, 7, 0xacd4ef233e47d9ULL) + .Append(kLittleEndian, 2, 0x5311ULL) + .Append(kBigEndian, 8, h) + .Append(kLittleEndian, 1, a) + .Append(kBigEndian, 8, 0x4668d5f1c93637a1ULL) + .Append(kLittleEndian, 1, 0x65ULL); + a = 0x79ac9bd8aa256b35ULL; + b = 0x22d13097ef86c91cULL; + c = 0xf204968b0a05862fULL; + d = 0x163177f15a0eb4ecULL; + e = 0xbd1b0f1d977f2246ULL; + f = 0x2b0842eee83c6461ULL; + g = 0x92f4b928a4bf875eULL; + h = 0x61a199a8f7286ba6ULL; + ASSERT_EQ(8 * 18U, section.Size()); + ASSERT_TRUE(section.GetContents(&contents)); + + static const u_int8_t expected[] = { + 0x35, 0xa6, 0x6b, 0x28, 0xf7, 0xa8, 0x99, 0xa1, 0x61, + 0x8b, 0x39, 0x44, 0x8f, 0x44, 0x40, 0x65, 0xa5, 0x0e, + 0xc9, 0x1c, 0x5e, 0x87, 0xbf, 0xa4, 0x28, 0xb9, 0xf4, + 0xcf, 0x15, 0x4a, 0x72, 0xc5, 0x04, 0x4f, 0x69, 0x29, + 0x05, 0x86, 0x2f, 0x61, 0x64, 0x3c, 0xe8, 0xee, 0x42, + 0x8c, 0x3f, 0xfd, 0x7a, 0x18, 0x80, 0xba, 0x11, 0x6f, + 0x5a, 0x0e, 0xb4, 0xec, 0x46, 0x22, 0x7f, 0x97, 0x1d, + 0x2f, 0xda, 0x24, 0x72, 0x3f, 0x42, 0x2d, 0xa0, 0x0a, + 0x1d, 0x97, 0x7f, 0x22, 0x46, 0xec, 0xb4, 0x0e, 0x5a, + 0x53, 0xba, 0x43, 0x21, 0x38, 0x60, 0xae, 0x39, 0xf1, + 0x42, 0xee, 0xe8, 0x3c, 0x64, 0x61, 0x2f, 0x86, 0x05, + 0x16, 0x8e, 0x43, 0x6a, 0xf7, 0x16, 0x89, 0xf1, 0x3e, + 0xf4, 0xb9, 0x28, 0xa4, 0xbf, 0x87, 0x5e, 0x1c, 0xc9, + 0xac, 0xd4, 0xef, 0x23, 0x3e, 0x47, 0xd9, 0x11, 0x53, + 0x61, 0xa1, 0x99, 0xa8, 0xf7, 0x28, 0x6b, 0xa6, 0x35, + 0x46, 0x68, 0xd5, 0xf1, 0xc9, 0x36, 0x37, 0xa1, 0x65, + }; + + ASSERT_TRUE(0 == memcmp(contents.data(), expected, sizeof(expected))); +} + +TEST_F(Append, Section) { + section.Append("murder"); + { + Section middle; + middle.Append(" she"); + section.Append(middle); + } + section.Append(" wrote"); + EXPECT_EQ(16U, section.Size()); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_STREQ(contents.c_str(), "murder she wrote"); +} + +TEST_F(Append, SectionRefs) { + section.Append("sugar "); + Label l; + { + Section middle; + Label m; + middle.B32(m); + section.Append(middle); + m = 0x66726565; + } + section.Append(" jazz"); + EXPECT_EQ(15U, section.Size()); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_STREQ(contents.c_str(), "sugar free jazz"); +} + +TEST_F(Append, LEB128_0) { + section.LEB128(0); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\0", 1), contents); +} + +TEST_F(Append, LEB128_0x3f) { + section.LEB128(0x3f); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\x3f", 1), contents); +} + +TEST_F(Append, LEB128_0x40) { + section.LEB128(0x40); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\xc0\x00", 2), contents); +} + +TEST_F(Append, LEB128_0x7f) { + section.LEB128(0x7f); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\xff\x00", 2), contents); +} + +TEST_F(Append, LEB128_0x80) { + section.LEB128(0x80); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\x80\x01", 2), contents); +} + +TEST_F(Append, LEB128_0xff) { + section.LEB128(0xff); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\xff\x01", 2), contents); +} + +TEST_F(Append, LEB128_0x1fff) { + section.LEB128(0x1fff); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\xff\x3f", 2), contents); +} + +TEST_F(Append, LEB128_0x2000) { + section.LEB128(0x2000); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\x80\xc0\x00", 3), contents); +} + +TEST_F(Append, LEB128_n1) { + section.LEB128(-1); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\x7f", 1), contents); +} + +TEST_F(Append, LEB128_n0x40) { + section.LEB128(-0x40); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\x40", 1), contents); +} + +TEST_F(Append, LEB128_n0x41) { + section.LEB128(-0x41); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\xbf\x7f", 2), contents); +} + +TEST_F(Append, LEB128_n0x7f) { + section.LEB128(-0x7f); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\x81\x7f", 2), contents); +} + +TEST_F(Append, LEB128_n0x80) { + section.LEB128(-0x80); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\x80\x7f", 2), contents); +} + +TEST_F(Append, LEB128_n0x2000) { + section.LEB128(-0x2000); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\x80\x40", 2), contents); +} + +TEST_F(Append, LEB128_n0x2001) { + section.LEB128(-0x2001); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\xff\xbf\x7f", 3), contents); +} + +TEST_F(Append,ULEB128_0) { + section.ULEB128(0); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\0", 1), contents); +} + +TEST_F(Append,ULEB128_1) { + section.ULEB128(1); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\x01", 1), contents); +} + +TEST_F(Append,ULEB128_0x3f) { + section.ULEB128(0x3f); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\x3f", 1), contents); +} + +TEST_F(Append,ULEB128_0x40) { + section.ULEB128(0x40); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\x40", 1), contents); +} + +TEST_F(Append,ULEB128_0x7f) { + section.ULEB128(0x7f); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\x7f", 1), contents); +} + +TEST_F(Append,ULEB128_0x80) { + section.ULEB128(0x80); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\x80\x01", 2), contents); +} + +TEST_F(Append,ULEB128_0xff) { + section.ULEB128(0xff); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\xff\x01", 2), contents); +} + +TEST_F(Append,ULEB128_0x100) { + section.ULEB128(0x100); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\x80\x02", 2), contents); +} + +TEST_F(Append,ULEB128_0x1fff) { + section.ULEB128(0x1fff); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\xff\x3f", 2), contents); +} + +TEST_F(Append,ULEB128_0x2000) { + section.ULEB128(0x2000); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\x80\x40", 2), contents); +} + +TEST_F(Append,ULEB128_0x3fff) { + section.ULEB128(0x3fff); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\xff\x7f", 2), contents); +} + +TEST_F(Append,ULEB128_0x4000) { + section.ULEB128(0x4000); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\x80\x80\x01", 3), contents); +} + +TEST_F(Append,ULEB128_12857) { + section.ULEB128(12857); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\xb9\x64", 2), contents); +} + +TEST_F(Append, LEBChain) { + section.LEB128(-0x80).ULEB128(12857).Append("*"); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(string("\x80\x7f\xb9\x64*", 5), contents); +} + + +class GetContents: public SectionFixture, public Test { }; + +TEST_F(GetContents, Undefined) { + Label l; + section.Append(kLittleEndian, 8, l); + ASSERT_FALSE(section.GetContents(&contents)); +} + +TEST_F(GetContents, ClearsContents) { + section.Append((size_t) 10, '*'); + EXPECT_EQ(10U, section.Size()); + EXPECT_TRUE(section.GetContents(&contents)); + EXPECT_EQ(0U, section.Size()); +} + +TEST_F(GetContents, ClearsReferences) { + Label l; + section.Append(kBigEndian, 1, l); + l = 42; + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_BYTES(contents, I1(42)); + ASSERT_TRUE(section.GetContents(&contents)); // should not die +} + +class Miscellanea: public SectionFixture, public Test { }; + +TEST_F(Miscellanea, Clear) { + section.Append("howdy"); + Label l; + section.L32(l); + EXPECT_EQ(9U, section.Size()); + section.Clear(); + EXPECT_EQ(0U, section.Size()); + l = 0x8d231bf0U; + ASSERT_TRUE(section.GetContents(&contents)); // should not die +} + +TEST_F(Miscellanea, Align) { + section.Append("*"); + EXPECT_EQ(1U, section.Size()); + section.Align(4).Append("*"); + EXPECT_EQ(5U, section.Size()); + section.Append("*").Align(2); + EXPECT_EQ(6U, section.Size()); +} + +TEST_F(Miscellanea, AlignPad) { + section.Append("*"); + EXPECT_EQ(1U, section.Size()); + section.Align(4, ' ').Append("*"); + EXPECT_EQ(5U, section.Size()); + section.Append("*").Align(2, ' '); + EXPECT_EQ(6U, section.Size()); + ASSERT_TRUE(section.GetContents(&contents)); + ASSERT_EQ(string("* **"), contents); +} + +TEST_F(Miscellanea, StartHereMark) { + Label m; + section.Append(42, ' ').Mark(&m).Append(13, '+'); + EXPECT_EQ(42U, m - section.start()); + EXPECT_EQ(42U + 13U, section.Here() - section.start()); + EXPECT_FALSE(section.start().IsKnownConstant()); + EXPECT_FALSE(m.IsKnownConstant()); + EXPECT_FALSE(section.Here().IsKnownConstant()); +} + +TEST_F(Miscellanea, Endianness) { + section.set_endianness(kBigEndian); + EXPECT_EQ(kBigEndian, section.endianness()); + section.set_endianness(kLittleEndian); + EXPECT_EQ(kLittleEndian, section.endianness()); +}