aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjimblandy <jimblandy@4c0a9323-5329-0410-9bdc-e9ce6186880e>2010-03-16 16:20:34 +0000
committerjimblandy <jimblandy@4c0a9323-5329-0410-9bdc-e9ce6186880e>2010-03-16 16:20:34 +0000
commit9244496c6f875ef1f7166d65f218d57ae92cabaa (patch)
treeefa23659ab561113dc083cdd23b814ea6ccee505
parentadd missing <string> include from r541 (diff)
downloadbreakpad-9244496c6f875ef1f7166d65f218d57ae92cabaa.tar.xz
Breakpad Processor: Add new unit tests for google_breakpad::Minidump
This also adds two new test utility class groups, TestAssembler and SynthMinidump. These are overkill for what I'm doing with them here (and may simply be overkill, period), but they make it easy to write unit tests for code that works on binary files or raw memory contents in a cross-platform way. I'm planning to use them for the DWARF CFI unwinding tests and the DWARF CFI parser tests. a=jimblandy, r=nealsid git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@547 4c0a9323-5329-0410-9bdc-e9ce6186880e
-rw-r--r--Makefile.am37
-rw-r--r--Makefile.in339
-rw-r--r--src/processor/minidump_unittest.cc443
-rw-r--r--src/processor/synth_minidump.cc309
-rw-r--r--src/processor/synth_minidump.h357
-rw-r--r--src/processor/synth_minidump_unittest.cc280
-rw-r--r--src/processor/synth_minidump_unittest_data.h246
-rw-r--r--src/processor/test_assembler.cc357
-rw-r--r--src/processor/test_assembler.h472
-rw-r--r--src/processor/test_assembler_unittest.cc1644
10 files changed, 4472 insertions, 12 deletions
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 <cstdlib>
#include <iostream>
#include <fstream>
#include <sstream>
+#include <stdlib.h>
#include <string>
#include <vector>
#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
+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);
-int main(int argc, char* argv[]) {
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
+ 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 <jimb@mozilla.com> <jimb@red-bean.com>
+
+// 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<SynthMinidump::Section *>(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<SynthMinidump::Section *>(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<TestAssembler::Section &>(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 <jimb@mozilla.com> <jimb@red-bean.com>
+
+// 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 <cassert>
+#include <iostream>
+#include <string>
+
+#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<typename Element>
+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> thread_list_;
+
+ // This minidump's module list. We construct this incrementally from
+ // Add(Module *) calls.
+ List<Module> 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<SynthMinidump::Section> 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 <jimb@mozilla.com> <jimb@red-bean.com>
+
+// test_assembler_unittest.cc: Unit tests for google_breakpad::TestAssembler.
+
+#include <sstream>
+#include <string>
+
+#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(&section1);
+ 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(&section);
+ 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(&section);
+ 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(&section);
+ 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<Section> 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<Section> list(dump, 0x26c9f498);
+ Section section1(dump);
+ section1.Append("section one contents");
+ EXPECT_TRUE(list.Empty());
+ list.Add(&section1);
+ EXPECT_FALSE(list.Empty());
+ Section section2(dump);
+ section2.Append("section two contents");
+ list.Add(&section2);
+ 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(&section);
+ 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 <jimb@mozilla.com> <jimb@red-bean.com>
+
+// test_assembler.cc: Implementation of google_breakpad::TestAssembler.
+// See test_assembler.h for details.
+
+#include <cassert>
+#include <cstdio>
+#include <iterator>
+
+#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<typename Inserter>
+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<string>(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<string>(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<string>(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 &section) {
+ size_t base = contents_.size();
+ contents_.append(section.contents_);
+ for (vector<Reference>::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 <jimb@mozilla.com> <jimb@red-bean.com>
+
+// 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 <list>
+#include <vector>
+#include <string>
+
+#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<N> 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<const char *>(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 &section);
+
+ // 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 <ENDIANNESS><BITWIDTH>:
+ // <ENDIANNESS> is either 'L' (little-endian, least significant byte first),
+ // 'B' (big-endian, most significant byte first), or
+ // 'D' (default, the section's default endianness)
+ // <BITWIDTH> is 8, 16, 32, or 64.
+ //
+ // Since endianness doesn't matter for a single byte, all the
+ // <BITWIDTH>=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<Reference> 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 <jimb@mozilla.com> <jimb@red-bean.com>
+
+// test_assembler_unittest.cc: Unit tests for google_breakpad::TestAssembler.
+
+#include <string>
+#include <string.h>
+
+#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());
+}