183e085b7a331c96237cf8e814f97b3ef4c36a70fjimblandy// Copyright (c) 2010 Google Inc.
252cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy// All rights reserved.
352cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy//
452cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy// Redistribution and use in source and binary forms, with or without
552cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy// modification, are permitted provided that the following conditions are
652cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy// met:
752cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy//
852cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy//     * Redistributions of source code must retain the above copyright
952cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy// notice, this list of conditions and the following disclaimer.
1052cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy//     * Redistributions in binary form must reproduce the above
1152cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy// copyright notice, this list of conditions and the following disclaimer
1252cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy// in the documentation and/or other materials provided with the
1352cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy// distribution.
1452cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy//     * Neither the name of Google Inc. nor the names of its
1552cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy// contributors may be used to endorse or promote products derived from
1652cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy// this software without specific prior written permission.
1752cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy//
1852cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1952cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2052cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2152cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2252cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2352cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2452cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2552cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2652cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2752cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2852cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2952cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
30c50e7c604cd1b12bba9421b0a95357fc942ecd7cjimblandy// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
31c50e7c604cd1b12bba9421b0a95357fc942ecd7cjimblandy
32c50e7c604cd1b12bba9421b0a95357fc942ecd7cjimblandy// module_unittest.cc: Unit tests for google_breakpad::Module.
3352cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
34e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek#include <errno.h>
35e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek#include <stdio.h>
36e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek#include <stdlib.h>
37e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek#include <string.h>
3852cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
3952cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy#include <algorithm>
403ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarek#include <sstream>
4152cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy#include <string>
4252cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
4352cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy#include "breakpad_googletest_includes.h"
4487855248f1fab83caf002418196a34051d359f2cjimblandy#include "common/module.h"
454e518a4357a2d1c379d4a91df6d4e153ee791101ivan.penkov@gmail.com#include "common/using_std_string.h"
4652cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
473e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandyusing google_breakpad::Module;
483ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarekusing std::stringstream;
4952cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandyusing std::vector;
503e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandyusing testing::ContainerEq;
5152cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
524ac61acb3a7dad6ce722fe07564be8ec92713228dmaclachstatic Module::Function *generate_duplicate_function(const string &name) {
530dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org  const Module::Address DUP_ADDRESS = 0xd35402aac7a7ad5cLL;
540dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org  const Module::Address DUP_SIZE = 0x200b26e605f99071LL;
550dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org  const Module::Address DUP_PARAMETER_SIZE = 0xf14ac4fed48c4a99LL;
560dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org
576105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org  Module::Function *function = new Module::Function(name, DUP_ADDRESS);
580dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org  function->size = DUP_SIZE;
590dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org  function->parameter_size = DUP_PARAMETER_SIZE;
600dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org  return function;
610dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org}
620dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org
6352cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy#define MODULE_NAME "name with spaces"
6452cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy#define MODULE_OS "os-name"
6552cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy#define MODULE_ARCH "architecture"
6652cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy#define MODULE_ID "id-string"
6752cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
6852cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandyTEST(Write, Header) {
693ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarek  stringstream s;
7052cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
7106e17f8d31507e3993609a9495dcaac02d96b4adted.mielczarek@gmail.com  m.Write(s, ALL_SYMBOL_DATA);
723ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarek  string contents = s.str();
7352cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n",
7452cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy               contents.c_str());
7552cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy}
7652cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
7752cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandyTEST(Write, OneLineFunc) {
783ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarek  stringstream s;
7952cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
8052cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
8152cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  Module::File *file = m.FindFile("file_name.cc");
826105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org  Module::Function *function = new Module::Function(
836105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org      "function_name", 0xe165bf8023b9d9abLL);
843e60d65111607f401461ff15981a463cde8f744ajimblandy  function->size = 0x1e4bb0eb1cbf5b09LL;
853e60d65111607f401461ff15981a463cde8f744ajimblandy  function->parameter_size = 0x772beee89114358aLL;
8652cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  Module::Line line = { 0xe165bf8023b9d9abLL, 0x1e4bb0eb1cbf5b09LL,
8752cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy                        file, 67519080 };
883e60d65111607f401461ff15981a463cde8f744ajimblandy  function->lines.push_back(line);
8952cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  m.AddFunction(function);
9052cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
9106e17f8d31507e3993609a9495dcaac02d96b4adted.mielczarek@gmail.com  m.Write(s, ALL_SYMBOL_DATA);
923ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarek  string contents = s.str();
9352cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
9452cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy               "FILE 0 file_name.cc\n"
9552cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy               "FUNC e165bf8023b9d9ab 1e4bb0eb1cbf5b09 772beee89114358a"
9652cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy               " function_name\n"
9752cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy               "e165bf8023b9d9ab 1e4bb0eb1cbf5b09 67519080 0\n",
9852cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy               contents.c_str());
9952cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy}
10052cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
10152cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandyTEST(Write, RelativeLoadAddress) {
1023ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarek  stringstream s;
10352cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
10452cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
10552cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  // Some source files.  We will expect to see them in lexicographic order.
10652cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  Module::File *file1 = m.FindFile("filename-b.cc");
10752cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  Module::File *file2 = m.FindFile("filename-a.cc");
10852cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
10952cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  // A function.
1106105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org  Module::Function *function = new Module::Function(
1116105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org      "A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)", 0xbec774ea5dd935f3LL);
1123e60d65111607f401461ff15981a463cde8f744ajimblandy  function->size = 0x2922088f98d3f6fcLL;
1133e60d65111607f401461ff15981a463cde8f744ajimblandy  function->parameter_size = 0xe5e9aa008bd5f0d0LL;
11452cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
11552cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  // Some source lines.  The module should not sort these.
11652cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  Module::Line line1 = { 0xbec774ea5dd935f3LL, 0x1c2be6d6c5af2611LL,
11752cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy                         file1, 41676901 };
11852cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  Module::Line line2 = { 0xdaf35bc123885c04LL, 0xcf621b8d324d0ebLL,
11952cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy                         file2, 67519080 };
1203e60d65111607f401461ff15981a463cde8f744ajimblandy  function->lines.push_back(line2);
1213e60d65111607f401461ff15981a463cde8f744ajimblandy  function->lines.push_back(line1);
12252cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
12352cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  m.AddFunction(function);
12452cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
1253e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // Some stack information.
1263e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  Module::StackFrameEntry *entry = new Module::StackFrameEntry();
1273e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry->address = 0x30f9e5c83323973dULL;
1283e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry->size = 0x49fc9ca7c7c13dc2ULL;
1293e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry->initial_rules[".cfa"] = "he was a handsome man";
1303e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry->initial_rules["and"] = "what i want to know is";
1313e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry->rule_changes[0x30f9e5c83323973eULL]["how"] =
1323e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy    "do you like your blueeyed boy";
1333e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry->rule_changes[0x30f9e5c83323973eULL]["Mister"] = "Death";
1343e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  m.AddStackFrameEntry(entry);
1353e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
13625b512d64dc9ec959d646151cf0cdc403ea0c335jimblandy  // Set the load address.  Doing this after adding all the data to
13725b512d64dc9ec959d646151cf0cdc403ea0c335jimblandy  // the module must work fine.
13825b512d64dc9ec959d646151cf0cdc403ea0c335jimblandy  m.SetLoadAddress(0x2ab698b0b6407073LL);
13925b512d64dc9ec959d646151cf0cdc403ea0c335jimblandy
14006e17f8d31507e3993609a9495dcaac02d96b4adted.mielczarek@gmail.com  m.Write(s, ALL_SYMBOL_DATA);
1413ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarek  string contents = s.str();
14252cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
14352cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy               "FILE 0 filename-a.cc\n"
14452cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy               "FILE 1 filename-b.cc\n"
14552cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy               "FUNC 9410dc39a798c580 2922088f98d3f6fc e5e9aa008bd5f0d0"
14652cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy               " A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)\n"
14752cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy               "b03cc3106d47eb91 cf621b8d324d0eb 67519080 0\n"
1483e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy               "9410dc39a798c580 1c2be6d6c5af2611 41676901 1\n"
1493e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy               "STACK CFI INIT 6434d177ce326ca 49fc9ca7c7c13dc2"
1503e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy               " .cfa: he was a handsome man"
1513e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy               " and: what i want to know is\n"
1523e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy               "STACK CFI 6434d177ce326cb"
1533e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy               " Mister: Death"
1543e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy               " how: do you like your blueeyed boy\n",
15552cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy               contents.c_str());
15652cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy}
15752cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
15852cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandyTEST(Write, OmitUnusedFiles) {
15952cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
16052cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
16152cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  // Create some source files.
16252cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  Module::File *file1 = m.FindFile("filename1");
1638d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  m.FindFile("filename2");  // not used by any line
16452cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  Module::File *file3 = m.FindFile("filename3");
16552cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
16652cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  // Create a function.
1676105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org  Module::Function *function = new Module::Function(
1686105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org      "function_name", 0x9b926d464f0b9384LL);
1693e60d65111607f401461ff15981a463cde8f744ajimblandy  function->size = 0x4f524a4ba795e6a6LL;
1703e60d65111607f401461ff15981a463cde8f744ajimblandy  function->parameter_size = 0xbbe8133a6641c9b7LL;
17152cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
17252cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  // Source files that refer to some files, but not others.
17352cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  Module::Line line1 = { 0x595fa44ebacc1086LL, 0x1e1e0191b066c5b3LL,
17452cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy                         file1, 137850127 };
17552cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  Module::Line line2 = { 0x401ce8c8a12d25e3LL, 0x895751c41b8d2ce2LL,
17652cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy                         file3, 28113549 };
1773e60d65111607f401461ff15981a463cde8f744ajimblandy  function->lines.push_back(line1);
1783e60d65111607f401461ff15981a463cde8f744ajimblandy  function->lines.push_back(line2);
17952cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  m.AddFunction(function);
18052cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
18152cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  m.AssignSourceIds();
1820dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org
18352cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  vector<Module::File *> vec;
18452cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  m.GetFiles(&vec);
18552cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  EXPECT_EQ((size_t) 3, vec.size());
1863e60d65111607f401461ff15981a463cde8f744ajimblandy  EXPECT_STREQ("filename1", vec[0]->name.c_str());
1873e60d65111607f401461ff15981a463cde8f744ajimblandy  EXPECT_NE(-1, vec[0]->source_id);
18852cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  // Expect filename2 not to be used.
1893e60d65111607f401461ff15981a463cde8f744ajimblandy  EXPECT_STREQ("filename2", vec[1]->name.c_str());
1903e60d65111607f401461ff15981a463cde8f744ajimblandy  EXPECT_EQ(-1, vec[1]->source_id);
1913e60d65111607f401461ff15981a463cde8f744ajimblandy  EXPECT_STREQ("filename3", vec[2]->name.c_str());
1923e60d65111607f401461ff15981a463cde8f744ajimblandy  EXPECT_NE(-1, vec[2]->source_id);
19352cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
1943ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarek  stringstream s;
19506e17f8d31507e3993609a9495dcaac02d96b4adted.mielczarek@gmail.com  m.Write(s, ALL_SYMBOL_DATA);
1963ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarek  string contents = s.str();
19752cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
19852cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy               "FILE 0 filename1\n"
19952cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy               "FILE 1 filename3\n"
20052cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy               "FUNC 9b926d464f0b9384 4f524a4ba795e6a6 bbe8133a6641c9b7"
20152cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy               " function_name\n"
20252cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy               "595fa44ebacc1086 1e1e0191b066c5b3 137850127 0\n"
20352cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy               "401ce8c8a12d25e3 895751c41b8d2ce2 28113549 1\n",
20452cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy               contents.c_str());
20552cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy}
20652cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
2078d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.orgTEST(Write, NoCFI) {
2088d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  stringstream s;
2098d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
2108d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org
2118d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  // Some source files.  We will expect to see them in lexicographic order.
2128d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  Module::File *file1 = m.FindFile("filename.cc");
2138d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org
2148d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  // A function.
2156105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org  Module::Function *function = new Module::Function(
2166105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org      "A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)", 0xbec774ea5dd935f3LL);
2178d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  function->size = 0x2922088f98d3f6fcLL;
2188d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  function->parameter_size = 0xe5e9aa008bd5f0d0LL;
2198d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org
2208d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  // Some source lines.  The module should not sort these.
2218d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  Module::Line line1 = { 0xbec774ea5dd935f3LL, 0x1c2be6d6c5af2611LL,
2228d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org                         file1, 41676901 };
2238d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  function->lines.push_back(line1);
2248d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org
2258d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  m.AddFunction(function);
2268d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org
2278d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  // Some stack information.
2288d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  Module::StackFrameEntry *entry = new Module::StackFrameEntry();
2298d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  entry->address = 0x30f9e5c83323973dULL;
2308d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  entry->size = 0x49fc9ca7c7c13dc2ULL;
2318d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  entry->initial_rules[".cfa"] = "he was a handsome man";
2328d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  entry->initial_rules["and"] = "what i want to know is";
2338d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  entry->rule_changes[0x30f9e5c83323973eULL]["how"] =
2348d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org    "do you like your blueeyed boy";
2358d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  entry->rule_changes[0x30f9e5c83323973eULL]["Mister"] = "Death";
2368d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  m.AddStackFrameEntry(entry);
2378d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org
2388d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  // Set the load address.  Doing this after adding all the data to
2398d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  // the module must work fine.
2408d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  m.SetLoadAddress(0x2ab698b0b6407073LL);
2418d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org
24206e17f8d31507e3993609a9495dcaac02d96b4adted.mielczarek@gmail.com  m.Write(s, NO_CFI);
2438d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  string contents = s.str();
2448d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org  EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
2458d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org               "FILE 0 filename.cc\n"
2468d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org               "FUNC 9410dc39a798c580 2922088f98d3f6fc e5e9aa008bd5f0d0"
2478d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org               " A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)\n"
2488d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org               "9410dc39a798c580 1c2be6d6c5af2611 41676901 0\n",
2498d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org               contents.c_str());
2508d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org}
2518d54c7509234e9a4918046c12dcb138489f06990thestig@chromium.org
25252cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandyTEST(Construct, AddFunctions) {
2533ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarek  stringstream s;
25452cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
25552cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
25652cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  // Two functions.
2576105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org  Module::Function *function1 = new Module::Function(
2586105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org      "_without_form", 0xd35024aa7ca7da5cLL);
2593e60d65111607f401461ff15981a463cde8f744ajimblandy  function1->size = 0x200b26e605f99071LL;
2603e60d65111607f401461ff15981a463cde8f744ajimblandy  function1->parameter_size = 0xf14ac4fed48c4a99LL;
26152cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
2626105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org  Module::Function *function2 = new Module::Function(
2636105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org      "_and_void", 0x2987743d0b35b13fLL);
2643e60d65111607f401461ff15981a463cde8f744ajimblandy  function2->size = 0xb369db048deb3010LL;
2653e60d65111607f401461ff15981a463cde8f744ajimblandy  function2->parameter_size = 0x938e556cb5a79988LL;
26652cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
26752cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  // Put them in a vector.
26852cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  vector<Module::Function *> vec;
26952cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  vec.push_back(function1);
27052cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  vec.push_back(function2);
27152cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
27252cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  m.AddFunctions(vec.begin(), vec.end());
27352cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
27406e17f8d31507e3993609a9495dcaac02d96b4adted.mielczarek@gmail.com  m.Write(s, ALL_SYMBOL_DATA);
2753ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarek  string contents = s.str();
27652cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
27752cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy               "FUNC 2987743d0b35b13f b369db048deb3010 938e556cb5a79988"
2780dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org               " _and_void\n"
2790dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org               "FUNC d35024aa7ca7da5c 200b26e605f99071 f14ac4fed48c4a99"
2800dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org               " _without_form\n",
28152cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy               contents.c_str());
28252cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
28352cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  // Check that m.GetFunctions returns the functions we expect.
28452cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  vec.clear();
28552cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  m.GetFunctions(&vec, vec.end());
28652cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  EXPECT_TRUE(vec.end() != find(vec.begin(), vec.end(), function1));
28752cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  EXPECT_TRUE(vec.end() != find(vec.begin(), vec.end(), function2));
28852cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  EXPECT_EQ((size_t) 2, vec.size());
28952cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy}
29052cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy
2913e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandyTEST(Construct, AddFrames) {
2923ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarek  stringstream s;
2933e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
2943e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
2953e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // First STACK CFI entry, with no initial rules or deltas.
2963e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  Module::StackFrameEntry *entry1 = new Module::StackFrameEntry();
2973e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry1->address = 0xddb5f41285aa7757ULL;
2983e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry1->size = 0x1486493370dc5073ULL;
2993e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  m.AddStackFrameEntry(entry1);
3000dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org
3013e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // Second STACK CFI entry, with initial rules but no deltas.
3023e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  Module::StackFrameEntry *entry2 = new Module::StackFrameEntry();
3033e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry2->address = 0x8064f3af5e067e38ULL;
3043e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry2->size = 0x0de2a5ee55509407ULL;
3053e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry2->initial_rules[".cfa"] = "I think that I shall never see";
3063e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry2->initial_rules["stromboli"] = "a poem lovely as a tree";
3073e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry2->initial_rules["cannoli"] = "a tree whose hungry mouth is prest";
3083e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  m.AddStackFrameEntry(entry2);
3093e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
3103e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // Third STACK CFI entry, with initial rules and deltas.
3113e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  Module::StackFrameEntry *entry3 = new Module::StackFrameEntry();
3123e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry3->address = 0x5e8d0db0a7075c6cULL;
3133e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry3->size = 0x1c7edb12a7aea229ULL;
3143e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry3->initial_rules[".cfa"] = "Whose woods are these";
3153e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry3->rule_changes[0x47ceb0f63c269d7fULL]["calzone"] =
3163e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy    "the village though";
3173e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry3->rule_changes[0x47ceb0f63c269d7fULL]["cannoli"] =
3183e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy    "he will not see me stopping here";
3193e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry3->rule_changes[0x36682fad3763ffffULL]["stromboli"] =
3203e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy    "his house is in";
3213e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry3->rule_changes[0x36682fad3763ffffULL][".cfa"] =
3223e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy    "I think I know";
3233e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  m.AddStackFrameEntry(entry3);
3243e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
3253e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // Check that Write writes STACK CFI records properly.
32606e17f8d31507e3993609a9495dcaac02d96b4adted.mielczarek@gmail.com  m.Write(s, ALL_SYMBOL_DATA);
3273ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarek  string contents = s.str();
3283e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
3293e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy               "STACK CFI INIT ddb5f41285aa7757 1486493370dc5073 \n"
3303e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy               "STACK CFI INIT 8064f3af5e067e38 de2a5ee55509407"
3313e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy               " .cfa: I think that I shall never see"
3323e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy               " cannoli: a tree whose hungry mouth is prest"
3333e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy               " stromboli: a poem lovely as a tree\n"
3343e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy               "STACK CFI INIT 5e8d0db0a7075c6c 1c7edb12a7aea229"
3353e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy               " .cfa: Whose woods are these\n"
3363e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy               "STACK CFI 36682fad3763ffff"
3373e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy               " .cfa: I think I know"
3383e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy               " stromboli: his house is in\n"
3393e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy               "STACK CFI 47ceb0f63c269d7f"
3403e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy               " calzone: the village though"
3413e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy               " cannoli: he will not see me stopping here\n",
3423e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy               contents.c_str());
3433e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
3443e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // Check that GetStackFrameEntries works.
3453e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  vector<Module::StackFrameEntry *> entries;
3463e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  m.GetStackFrameEntries(&entries);
3473e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  ASSERT_EQ(3U, entries.size());
3483e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // Check first entry.
3493e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  EXPECT_EQ(0xddb5f41285aa7757ULL, entries[0]->address);
3503e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  EXPECT_EQ(0x1486493370dc5073ULL, entries[0]->size);
3513e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  ASSERT_EQ(0U, entries[0]->initial_rules.size());
3523e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  ASSERT_EQ(0U, entries[0]->rule_changes.size());
3533e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // Check second entry.
3543e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  EXPECT_EQ(0x8064f3af5e067e38ULL, entries[1]->address);
3553e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  EXPECT_EQ(0x0de2a5ee55509407ULL, entries[1]->size);
3563e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  ASSERT_EQ(3U, entries[1]->initial_rules.size());
3573e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  Module::RuleMap entry2_initial;
3583e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry2_initial[".cfa"] = "I think that I shall never see";
3593e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry2_initial["stromboli"] = "a poem lovely as a tree";
3603e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry2_initial["cannoli"] = "a tree whose hungry mouth is prest";
3613e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  EXPECT_THAT(entries[1]->initial_rules, ContainerEq(entry2_initial));
3623e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  ASSERT_EQ(0U, entries[1]->rule_changes.size());
3633e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  // Check third entry.
3643e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  EXPECT_EQ(0x5e8d0db0a7075c6cULL, entries[2]->address);
3653e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  EXPECT_EQ(0x1c7edb12a7aea229ULL, entries[2]->size);
3663e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  Module::RuleMap entry3_initial;
3673e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry3_initial[".cfa"] = "Whose woods are these";
3683e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  EXPECT_THAT(entries[2]->initial_rules, ContainerEq(entry3_initial));
3693e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  Module::RuleChangeMap entry3_changes;
3703e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry3_changes[0x36682fad3763ffffULL][".cfa"] = "I think I know";
3713e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry3_changes[0x36682fad3763ffffULL]["stromboli"] = "his house is in";
3723e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry3_changes[0x47ceb0f63c269d7fULL]["calzone"] = "the village though";
3733e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  entry3_changes[0x47ceb0f63c269d7fULL]["cannoli"] =
3743e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy    "he will not see me stopping here";
3753e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy  EXPECT_THAT(entries[2]->rule_changes, ContainerEq(entry3_changes));
3763e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy}
3773e768ed9c01a244cdb1bc0d6aec34fb25821fbccjimblandy
37852cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandyTEST(Construct, UniqueFiles) {
37952cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
38052cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  Module::File *file1 = m.FindFile("foo");
38152cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  Module::File *file2 = m.FindFile(string("bar"));
38252cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  Module::File *file3 = m.FindFile(string("foo"));
38352cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  Module::File *file4 = m.FindFile("bar");
38452cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  EXPECT_NE(file1, file2);
38552cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  EXPECT_EQ(file1, file3);
38652cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  EXPECT_EQ(file2, file4);
38752cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  EXPECT_EQ(file1, m.FindExistingFile("foo"));
38852cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy  EXPECT_TRUE(m.FindExistingFile("baz") == NULL);
38952cb2c6f4235dfaa3760ef37fe7082e9e99b0ebdjimblandy}
3900dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org
3910dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.orgTEST(Construct, DuplicateFunctions) {
3923ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarek  stringstream s;
3930dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org  Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
3940dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org
3950dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org  // Two functions.
3960dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org  Module::Function *function1 = generate_duplicate_function("_without_form");
3970dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org  Module::Function *function2 = generate_duplicate_function("_without_form");
3980dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org
3990dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org  m.AddFunction(function1);
4000dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org  m.AddFunction(function2);
4010dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org
40206e17f8d31507e3993609a9495dcaac02d96b4adted.mielczarek@gmail.com  m.Write(s, ALL_SYMBOL_DATA);
4033ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarek  string contents = s.str();
4040dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org  EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
4050dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org               "FUNC d35402aac7a7ad5c 200b26e605f99071 f14ac4fed48c4a99"
4060dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org               " _without_form\n",
4070dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org               contents.c_str());
4080dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org}
4090dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org
4100dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.orgTEST(Construct, FunctionsWithSameAddress) {
4113ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarek  stringstream s;
4120dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org  Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
4130dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org
4140dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org  // Two functions.
4150dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org  Module::Function *function1 = generate_duplicate_function("_without_form");
4160dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org  Module::Function *function2 = generate_duplicate_function("_and_void");
4170dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org
4180dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org  m.AddFunction(function1);
4190dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org  m.AddFunction(function2);
4200dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org
42106e17f8d31507e3993609a9495dcaac02d96b4adted.mielczarek@gmail.com  m.Write(s, ALL_SYMBOL_DATA);
4223ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarek  string contents = s.str();
4230dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org  EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
4240dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org               "FUNC d35402aac7a7ad5c 200b26e605f99071 f14ac4fed48c4a99"
4250dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org               " _and_void\n"
4260dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org               "FUNC d35402aac7a7ad5c 200b26e605f99071 f14ac4fed48c4a99"
4270dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org               " _without_form\n",
4280dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org               contents.c_str());
4290dd6c95b3fcf0bef0a473901e47eb4c23fb30f5bthestig@chromium.org}
430bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek
431bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek// Externs should be written out as PUBLIC records, sorted by
432bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek// address.
433bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarekTEST(Construct, Externs) {
4343ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarek  stringstream s;
435bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek  Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
436bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek
437bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek  // Two externs.
4386105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org  Module::Extern *extern1 = new Module::Extern(0xffff);
439bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek  extern1->name = "_abc";
4406105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org  Module::Extern *extern2 = new Module::Extern(0xaaaa);
441bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek  extern2->name = "_xyz";
442bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek
443bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek  m.AddExtern(extern1);
444bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek  m.AddExtern(extern2);
445bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek
44606e17f8d31507e3993609a9495dcaac02d96b4adted.mielczarek@gmail.com  m.Write(s, ALL_SYMBOL_DATA);
4473ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarek  string contents = s.str();
448bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek
449bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek  EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " "
450bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek               MODULE_ID " " MODULE_NAME "\n"
451bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek               "PUBLIC aaaa 0 _xyz\n"
452bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek               "PUBLIC ffff 0 _abc\n",
453bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek               contents.c_str());
454bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek}
455bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek
456bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek// Externs with the same address should only keep the first entry
457bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek// added.
458bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarekTEST(Construct, DuplicateExterns) {
4593ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarek  stringstream s;
460bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek  Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
461bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek
462bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek  // Two externs.
4636105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org  Module::Extern *extern1 = new Module::Extern(0xffff);
464bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek  extern1->name = "_xyz";
4656105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org  Module::Extern *extern2 = new Module::Extern(0xffff);
466bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek  extern2->name = "_abc";
467bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek
468bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek  m.AddExtern(extern1);
469bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek  m.AddExtern(extern2);
470bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek
47106e17f8d31507e3993609a9495dcaac02d96b4adted.mielczarek@gmail.com  m.Write(s, ALL_SYMBOL_DATA);
4723ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarek  string contents = s.str();
473bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek
474bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek  EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " "
475bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek               MODULE_ID " " MODULE_NAME "\n"
476bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek               "PUBLIC ffff 0 _xyz\n",
477bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek               contents.c_str());
478bf25801d837b8fc496bf9c3a34eac525d8a3d8aeted.mielczarek}
479cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org
480cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org// If there exists an extern and a function at the same address, only write
481cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org// out the FUNC entry.
482cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.orgTEST(Construct, FunctionsAndExternsWithSameAddress) {
483cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  stringstream s;
484cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
485cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org
486cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  // Two externs.
487cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  Module::Extern* extern1 = new Module::Extern(0xabc0);
488cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  extern1->name = "abc";
489cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  Module::Extern* extern2 = new Module::Extern(0xfff0);
490cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  extern2->name = "xyz";
491cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org
492cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  m.AddExtern(extern1);
493cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  m.AddExtern(extern2);
494cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org
495cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  Module::Function* function = new Module::Function("_xyz", 0xfff0);
496cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  function->size = 0x10;
497cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  function->parameter_size = 0;
498cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  m.AddFunction(function);
499cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org
500cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  m.Write(s, ALL_SYMBOL_DATA);
501cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  string contents = s.str();
502cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org
503cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " "
504cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org               MODULE_ID " " MODULE_NAME "\n"
505cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org               "FUNC fff0 10 0 _xyz\n"
506cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org               "PUBLIC abc0 0 abc\n",
507cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org               contents.c_str());
508cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org}
509cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org
510cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org// If there exists an extern and a function at the same address, only write
511cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org// out the FUNC entry. For ARM THUMB, the extern that comes from the ELF
512cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org// symbol section has bit 0 set.
513cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.orgTEST(Construct, FunctionsAndThumbExternsWithSameAddress) {
514cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  stringstream s;
515cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  Module m(MODULE_NAME, MODULE_OS, "arm", MODULE_ID);
516cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org
517cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  // Two THUMB externs.
518cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  Module::Extern* thumb_extern1 = new Module::Extern(0xabc1);
519cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  thumb_extern1->name = "thumb_abc";
520cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  Module::Extern* thumb_extern2 = new Module::Extern(0xfff1);
521cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  thumb_extern2->name = "thumb_xyz";
522cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org
523cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  Module::Extern* arm_extern1 = new Module::Extern(0xcc00);
524cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  arm_extern1->name = "arm_func";
525cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org
526cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  m.AddExtern(thumb_extern1);
527cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  m.AddExtern(thumb_extern2);
528cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  m.AddExtern(arm_extern1);
529cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org
530cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  // The corresponding function from the DWARF debug data have the actual
531cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  // address.
532cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  Module::Function* function = new Module::Function("_thumb_xyz", 0xfff0);
533cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  function->size = 0x10;
534cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  function->parameter_size = 0;
535cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  m.AddFunction(function);
536cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org
537cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  m.Write(s, ALL_SYMBOL_DATA);
538cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  string contents = s.str();
539cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org
540cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org  EXPECT_STREQ("MODULE " MODULE_OS " arm "
541cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org               MODULE_ID " " MODULE_NAME "\n"
542cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org               "FUNC fff0 10 0 _thumb_xyz\n"
543cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org               "PUBLIC abc1 0 thumb_abc\n"
544cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org               "PUBLIC cc00 0 arm_func\n",
545cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org               contents.c_str());
546cddd7bc13f11f73f25b435824bb4984feab59fb6thestig@chromium.org}
547