// -*- mode: C++ -*- // Copyright 2010 Google LLC // // 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 LLC 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 <[email protected]> <[email protected]> // 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 "common/using_std_string.h" #include "google_breakpad/common/breakpad_types.h" namespace google_breakpad { list; vector; namespace test_assembler { // 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 { … }; inline Label operator+(uint64_t a, const Label& l) { … } // 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 { … }; // 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 { … }; } // namespace test_assembler } // namespace google_breakpad #endif // PROCESSOR_TEST_ASSEMBLER_H_